C++从已实现的虚拟类中调用非虚拟方法
C++ Calling a non-virtual method from an implemented virtual class
我有一个接口,它也有一个普通的方法,那么我该如何调用它呢?
class Animal{
virtual void virtualFunction()=0;
}
class Cow : Animal{
virtual void virtualFunction(){}
void nonVirtualFunction(){}
}
class main{
Animal *a = new Cow();
a->virtualFunction();
}
^:这是有效的,但当我这样做时…
a->nonVirtualFunction();
它说类Animal没有这个方法,我当然知道,但是调用该方法的最佳方式是什么?
如果要调用Cow
的成员函数,首先不要将其存储在多态Animal
指针中:
Cow* c = new Cow();
c->nonVirtualFunction();
如果要以特定于Cow
的方式使用Cow
,那么将其存储在Animal*
中是没有意义的。
可以使用dynamic_cast
在运行时检查对象的动态类型:
Animal* a = new Cow();
if (Cow* c = dynamic_cast<Cow*>(a)) {
c->nonVirtualFunction();
}
然而,这通常是糟糕设计的标志。
您需要使用Cow指针来调用nonVirtualFunction。Animal指针是指向具有Animal接口的奶牛的SUBSET的指针。
调用nonVirtualFunction的唯一方法是获取Cow指针。
Cow *c = dynamic_cast<Cow*>(a);
会给你这样一个指针,假设a真的指向了一头牛。
为了更好地解释自己,我将使用真实名称来代替占位符:
class Animal{
virtual void move()=0;
}
class Cow : Animal{
virtual void move(){}
void moo(){}
}
int main () {
Animal *a = new Cow();
a->move();
a->moo(); // ERROR
}
当然,这是一个错误:你到底为什么要制作一个通用的Animal
moo
?所以问题不在于如何在任何Animal
上调用moo
;恰好这个调用毫无意义,编译器帮助我们注意到了这一点。
现在,Animal
可能有一个非虚拟方法,可以在任何动物身上调用,而无需在子类上重写,例如:
class Animal{
// Everything else, plus:
std::string Name() {return name;}
private:
std::string name;
}
int main () {
Animal *a = new Cow();
a->move();
std::string animalName = a->Name(); // OK
}
正如你所看到的,如果你有一个好的设计,问题就会消失。
相关文章:
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 当覆盖存在时调用基本虚拟"binded to object"函数
- C++ DLL 类导出、编译器"optimizes"虚拟调用
- 类型擦除的std::function与虚拟函数调用的开销
- 虚拟继承中来自基数的虚拟调用
- 通过在基类中虚拟调用派生类中的函数来访问派生类中的函数
- C++虚拟函数是正常调用还是虚拟调用
- 为什么C++虚拟调用并不比非虚拟调用慢多少
- 避免虚拟调用循环的模式
- C++11 标准::功能比虚拟调用慢
- 构造函数中的虚拟调用
- 为什么C++虚拟调用的成本取决于派生类的数量
- 为什么从构造函数对纯虚函数的虚拟调用是 UB,而标准允许调用非纯虚函数
- 优化后的虚拟调用成本
- 对于C++基类来说,存储"this"的值以供构造后的未来虚拟调用安全吗?
- 构造/销毁期间的虚拟调用
- 用FlasCC编译的c++程序使用-O4 (LTO)挂起虚拟调用
- 基构造函数中的 C++/CX 委托失败,并出现纯虚拟调用断言
- 如何将虚拟调用从未模板化的父级干净地分派到模板化的子级
- std::绑定和对基类方法的非虚拟调用