我有一个像这样的钻石多重继承场景:
A
/ \
B C
\ /
D
Run Code Online (Sandbox Code Playgroud)
公共父A定义了虚函数fn().
B和C都可以定义fn()吗?
如果是,那么下一个问题是 - D可以访问B和C的fn()而不消除歧义吗?我假设有一些语法...
而D是否有可能在不知道谁是B和C的情况下做到这一点?B和C可以替换为其他类,我希望D中的代码是通用的.
我想要做的是让D以某种方式枚举它在其祖先中具有的fn()的所有实例.这是否可能在某些其他方面表示虚函数?
我正在用C++编写,我想将一个未知类型(仅在运行时知道)传递给纯虚函数:
virtual void DoSomething(??? data);
Run Code Online (Sandbox Code Playgroud)
where DoSomething是派生类中纯虚函数的实现.
我打算使用模板,但因为它结果是虚函数和模板不能一起工作:C++类成员函数模板可以是虚拟的吗?
我想避免为我传递给函数的所有类使用基类(类似于C#中的对象).
提前致谢
来自Addison Wesley:C++模板
成员函数模板不能声明为虚拟.强加此约束是因为虚函数调用机制的通常实现使用固定大小的表,每个虚函数有一个条目.但是,在翻译整个程序之前,成员函数模板的实例化数量不固定.
以上引用是否意味着模板具有静态绑定,虚拟功能具有动态绑定,这就是不能有虚拟功能模板的原因?请查看是否可以用外行的语言进行解释.
如果你有这样的结构
struct A {
void func();
};
Run Code Online (Sandbox Code Playgroud)
和像这样的参考
A& a;
Run Code Online (Sandbox Code Playgroud)
你可以func像这样得到一个指向它的方法的指针:
someMethod(&A::func);
Run Code Online (Sandbox Code Playgroud)
现在,如果该方法是虚拟的并且您不知道它在运行时是什么,该怎么办?为什么你不能得到像这样的指针?
someMethod(&a.func);
Run Code Online (Sandbox Code Playgroud)
是否有可能获得指向该方法的指针?
c++ virtual-functions member-function-pointers function-pointers
我做了一些研究,找出为什么构造函数不能虚拟.我在这里巩固了我的理解.
我将首先解释什么是虚函数,然后根据第一个解释解释为什么构造函数不能是虚函数.
什么是virtual function?
虚函数是基类中的函数或方法,可以通过具有相同签名的函数在派生类中重新定义或覆盖.换句话说,虚函数允许在派生类中具有基类方法的自定义实现.它需要使用
virtual关键字声明.在虚函数调用时,决定在运行时选择函数定义的哪个版本(在基类或派生类中),具体取决于调用对象的类型(动态绑定).当函数声明为virtual时,它告诉编译器应该仅在运行时确定调用虚函数的对象的类型.然后根据对象的类型,函数调用应该绑定到函数定义,并且应该调用适当的函数.
为什么一个constructor不能虚拟?
当函数声明为virtual时,它告诉编译器应该仅在运行时确定调用该函数的对象的类型,然后根据对象的类型调用该函数的相应版本.
如果要将构造函数声明为virtual,它将告诉编译器应该在运行时确定将调用构造函数的对象类型.但是对于构造对象,应该在编译时而不是在运行时知道对象的确切类型.这就是构造函数不能虚拟的原因.
我希望SO成员纠正两个答案中的错误,如果有的话.我认为这对我和其他人有帮助,如果你可以通过重写它作为你的答案来纠正答案,而不是仅仅指出错误.
我知道params修饰符(将数组类型的一个参数转换为所谓的"参数数组")特别不是方法签名的一部分.现在考虑这个例子:
class Giraffid
{
public virtual void Eat(int[] leaves)
{
Console.WriteLine("G");
}
}
class Okapi : Giraffid
{
public override void Eat(params int[] leaves)
{
Console.WriteLine("O");
}
}
Run Code Online (Sandbox Code Playgroud)
编译时没有任何警告.然后说:
var okapi = new Okapi();
okapi.Eat(2, 4, 6); // will not compile!
Run Code Online (Sandbox Code Playgroud)
给出一个错误(No overload for method 'Eat' takes 3 arguments).
现在,我知道编译器会将params修改器转换为System.ParamArrayAttribute相关参数的应用程序.通常,将一个属性集合应用于虚方法的参数,然后在具有不同属性集的派生类中的重写方法中装饰"对应"参数是没有问题的.
然而,编译器选择params静默忽略我的关键字.相反,如果一个使它反过来,并且应用于params基类中的参数Giraffid,然后省略覆盖中的关键字Okapi,编译器选择用它来装饰两个方法System.ParamArrayAttribute.当然,我用IL DASM验证了这些东西.
我的问题:
这是记录在案的行为?我已经彻底搜索了C#语言规范,但没有发现任何提及.
我可以说至少Visual Studio开发环境对此感到困惑.当键入2, 4, 6在上述方法的调用,所述 …
任何人都可以这么好,并解释为什么这个代码显示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) 考虑以下:
在Xh:
class X
{
X();
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
X.cpp:
#include "X.h"
X::X()
{}
Run Code Online (Sandbox Code Playgroud)
尝试构建这个(我使用的是.dll目标,以避免在丢失的main上出现错误,我正在使用Visual Studio 2010):
错误1错误LNK2001:未解析的外部符号"private:virtual __thiscall X :: ~X(void)"(?? 1X @@ EAE @ XZ)
然而,小的修改导致成功构建:
XH:
class X
{
inline X(); // Now inlined, and everything builds
virtual ~X();
};
Run Code Online (Sandbox Code Playgroud)
要么
XH:
class X
{
X();
~X(); // No longer virtual, and everything builds
};
Run Code Online (Sandbox Code Playgroud)
当.dtor是虚拟的或者.ctor没有内联时,是什么导致链接器中未解析的外部?
编辑:
或者,或许更有趣的是,如果我将析构函数设置为非虚拟,或者如果我内联构造函数,为什么我没有得到未解析的外部?
B类覆盖了A类的纯虚函数"print()".C类继承了B类,并且具有"使用A :: print"语句.既然C类不是抽象类呢?
class A {
public :
virtual void print() =0;
};
class B:public A {
public:
void print();
};
void B :: print() {
cout << "\nClass B print ()";
}
class C : public B {
public:
using A::print;
};
void funca (A *a) {
// a->print(1);
}
void funcb (B *b) {
b->print();
}
void funcc (C *c) {
c->print();
}
int main() {
B b;
C c;
funca(&c);
funcb(&c);
funcc(&c);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Class …Run Code Online (Sandbox Code Playgroud) c++ ×8
c# ×2
overriding ×2
templates ×2
arduino ×1
constructor ×1
destructor ×1
firmware ×1
overloading ×1
params ×1