我有以下问题:
class Base
{
};
class Derived : public Base
{
};
class Different
{
};
class X
{
public:
template <typename T>
static const char *func(T *data)
{
// Do something generic...
return "Generic";
}
static const char *func(Base *data)
{
// Do something specific...
return "Specific";
}
};
Run Code Online (Sandbox Code Playgroud)
如果我现在这样做
Derived derived;
Different different;
std::cout << "Derived: " << X::func(&derived) << std::endl;
std::cout << "Different: " << X::func(&different) << std::endl;
Run Code Online (Sandbox Code Playgroud)
我明白了
Derived: Generic
Different: Generic
Run Code Online (Sandbox Code Playgroud)
但我想要的是,对于从Base派生的所有类,调用特定方法.所以结果应该是:
Derived: Specific
Different: …Run Code Online (Sandbox Code Playgroud) 我打字的时候遇到了这个问题man 2 open.它说开放有两种,一种有两个args,一种有三种!上次我检查时我们无法在C中重载功能.他们是怎么做到的?他们用C++写的吗?
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
Run Code Online (Sandbox Code Playgroud) 在PHP 5中,您可以使用魔术方法,重载某些类等.在C++中,只要参数类型不同,就可以实现存在的函数.有没有办法在PHP中执行此操作?
我想做的一个例子是:
class a {
function a() {
$this->list = array("1", "2");
}
}
$blah = new a();
count($blah);
Run Code Online (Sandbox Code Playgroud)
我想要等待返回2. IE计算类中特定数组的值.所以在C++中,我这样做的方式可能如下所示:
int count(a varName) { return count(varName->list); }
Run Code Online (Sandbox Code Playgroud)
基本上,我正在尝试简化大型应用程序的数据调用,所以我可以调用:
count($object);
Run Code Online (Sandbox Code Playgroud)
而不是
count($object->list);
Run Code Online (Sandbox Code Playgroud)
该列表可能是一个对象列表,因此根据它的使用方式,如果有人必须以当前的方式执行它,那么它可能是非常令人讨厌的声明:
count($object->list[0]->list[0]->list);
Run Code Online (Sandbox Code Playgroud)
那么,我可以制作类似的东西:
function count(a $object) {
count($object->list);
}
Run Code Online (Sandbox Code Playgroud)
我知道PHP的计数接受混合var,所以我不知道我是否可以覆盖单个类型.
可能重复:
NULL参数的方法重载
在下面的代码输出是
串
如果我用类型参数删除方法,String那么输出是
宾语
我知道当参数类型不完全匹配时方法的重载如何起作用但我无法理解如何将null视为Object和/或String参数.
对此有何解释?
class C {
static void m1(Object x) {
System.out.print("Object");
}
static void m1(String x) {
System.out.print("String");
}
public static void main(String[] args) {
m1(null);
}
}
Run Code Online (Sandbox Code Playgroud) 写点的时候
doit(43, 44, "hello");
Run Code Online (Sandbox Code Playgroud)
编译器知道要调用哪个重载方法.当我想通过反思做同样的事情时,我需要找出自己,方法是
doit(Integer, double, CharSequence...);
Run Code Online (Sandbox Code Playgroud)
并通过类似的东西获得它
Class[] types = {Integer.class, double.class, CharSequence[].class};
declaringClass.getDeclaredMethod("doit", types);
Run Code Online (Sandbox Code Playgroud)
我想知道是否已经允许我写一些东西了
Method m = getMethod(declaringClass, "doit", 43, 44, "hello");
Run Code Online (Sandbox Code Playgroud)
我想知道是否有人这样做了,因为JLS在这方面有点复杂.
实际上,行为与编译器完全相同是不可能的,因为在第1阶段,编译器只接受匹配而没有装箱和拆箱的方法.当getMethod从上面调用我的假设时,原语和它们的包装器之间的区别已经丢失(因为通过varargs传递参数时的自动装箱).这个问题似乎没有解决方案,所以让我们忽略它.
如答案所示,BeanUtils.invokeMethod接近.它应该找到最佳匹配,无论它意味着什么.查看MethodUtils.getMatchingAccessibleMethod显示了这一点
所以我正在寻找更好的东西.
在Fortran 90中,我们可以通过接口重载功能.但是,根据此站点,我们无法使用相同的参数名称定义这些函数.使用gfortran,它似乎不是一个问题,因为以下代码运行良好:
interface check
module procedure check_int, check_real
end interface
contains
subroutine check_int(cur, dname, func_name, fname)
integer, allocatable, intent(in) :: cur(:)
character(*) :: dname, func_name, fname
...
end subroutine
subroutine check_real(cur, dname, func_name, fname)
real, allocatable, intent(in) :: cur(:)
character(*) :: dname, func_name, fname
...
end subroutine
Run Code Online (Sandbox Code Playgroud)
那么,这样做是不好的做法吗?
编辑:使用关键字调用函数不会改变任何内容.
给定以下具有重载版本的伴随对象apply:
object List {
def apply[T](): List[T] = new Nil
def apply[T](x1: T): List[T] = new Cons(x1, new Nil)
def apply[T](x1: T, x2: T): List[T] = new Cons(x1, new Cons(x2, new Nil))
def apply[T](elems: T*): List[T] =
elems.foldRight(List[T])((elem, l) => new Cons(elem, l))
}
Run Code Online (Sandbox Code Playgroud)
和两个实例
List(1) // Error - Ambiguity
List('a', 'b') // Works fine
Run Code Online (Sandbox Code Playgroud)
scalac抱怨第一个实例化(对重载定义的模糊引用),因为单个参数和varargs方法都是同样具体的.
搜索stackoverflow我发现可以强制使用单个参数方法.List[Int](1)将使编译器使用def apply[T](x1: T).
我的问题是为什么第二个实例化def apply[T](x1: T, x2: T)没有额外的"提示" 匹配?换句话说,为什么两个参数方法比单个参数方法不是的varargs方法更 …
任何人都可以这么好,并解释为什么这个代码显示Derived.DoWork(double).我可以为这种行为提出一些解释,但我希望有人为我澄清这一点.
using System;
public class Base
{
public virtual void DoWork(int param) {
Console.WriteLine("Base.DoWork");
}
}
public class Derived : Base
{
public override void DoWork(int param) {
Console.WriteLine("Derived.DoWork(int)");
}
public void DoWork(double param) {
Console.WriteLine("Derived.DoWork(double)");
}
public static void Main() {
int val = 5;
Derived d = new Derived();
d.DoWork(val);
}
}
Run Code Online (Sandbox Code Playgroud) 例如,而不是
void shared_ptr::reset() noexcept;
template <typename Y>
void shared_ptr::reset(Y* ptr);
Run Code Online (Sandbox Code Playgroud)
人们可能会想到
template <typename Y = T>
void shared_ptr::reset(Y* ptr = nullptr);
Run Code Online (Sandbox Code Playgroud)
我认为这里的性能差异可以忽略不计,第二个版本更简洁.有没有具体的原因C++标准是第一种方式?
在同样的问题已经被问了科特林语言,默认参数为首选那里.
更新:
std::unique_ptr::reset()遵循默认参数设计(参见此处).所以我认为std::shared_ptr::reset()使用重载的原因是因为它们有不同的异常规范.
c++ api-design overloading language-lawyer default-arguments
我正在编写一个c ++库,它公开了一些仅由C#代码使用的函数.但是,由于我意外地错误输入了参数,我发现只要我不在cpp文件中使用(没有错误的版本)函数,即使没有任何警告,也可以成功编译和链接此代码.
struct Dummy { int a; double b; };
extern "C" void SetArray(Dummy* x, int cnt);
void SetArray(Dummy x, int cnt)
{
// a TODO placeholder.
}
Run Code Online (Sandbox Code Playgroud)
如何让编译器为这种情况抛出错误或警告?编译器选项-Wall已设置但仍然没有警告.使用tdmgcc 5.1.0.
overloading ×10
c++ ×3
java ×2
api-design ×1
c ×1
c# ×1
compilation ×1
countable ×1
extern ×1
fortran ×1
fortran90 ×1
linux ×1
manpage ×1
methods ×1
php ×1
reflection ×1
scala ×1
templates ×1