C++ 是否可以在不使用virtual关键字的情况下调用(同名)子函数?

C++ 是否可以在不使用virtual关键字的情况下调用(同名)子函数?,c++,polymorphism,C++,Polymorphism,我只是好奇。例如: #include <iostream> class Polygon { protected: int width, height; public: Polygon (int a, int b) : width(a), height(b) {} int area() { return 0; }; }; class Rectangle: public Polygon { public: Rectangle(int a

我只是好奇。例如:

#include <iostream>

class Polygon {
  protected:
    int width, height;

  public:
    Polygon (int a, int b) : width(a), height(b) {}

    int area() { return 0; };
};

class Rectangle: public Polygon {
  public:
    Rectangle(int a,int b) : Polygon(a,b) {}

    int area() { return width*height; }
};

int main () {
  Polygon * ppoly1 = new Rectangle (4,5);
  std::cout << ppoly1->area() << std::endl;
  delete ppoly1;
}   
#包括
类多边形{
受保护的:
int宽度、高度;
公众:
多边形(inta,intb):宽度(a),高度(b){}
int area(){return 0;};
};
类矩形:公共多边形{
公众:
矩形(inta,intb):多边形(a,b){}
int area(){返回宽度*高度;}
};
int main(){
多边形*ppoly1=新矩形(4,5);

std::cout area()如果函数不是虚拟函数,编译器将根据指针的类型(而不是对象的实际类型)决定调用哪个函数,因此可以使用强制转换:

std::cout << static_cast<Rectangle*>(ppoly1)->area() << std::endl;

std::cout area()如果函数不是虚拟函数,编译器将根据指针的类型(而不是对象的实际类型)决定调用哪个函数,因此您可以使用强制转换:

std::cout << static_cast<Rectangle*>(ppoly1)->area() << std::endl;
std::cout区域()
我可以调用对象矩形的area()函数而不在多边形上设置virtual area()

是的,如果您确信指针实际上指向一个
矩形
,您可以将
多边形*投射到一个矩形*

Polygon * ppoly1 = new Rectangle (4,5);
auto asRectangle = static_cast<Rectangle*>(ppoly1);
std::cout << asRectangle->area() << std::endl;
Polygon*ppoly1=新矩形(4,5);
自动asRectangle=静态_cast(ppoly1);
标准::cout区域()
我可以调用对象矩形的area()函数而不在多边形上设置virtual area()

是的,如果您确信
指针实际上指向一个
矩形,您可以将多边形*投射到一个矩形*

Polygon * ppoly1 = new Rectangle (4,5);
auto asRectangle = static_cast<Rectangle*>(ppoly1);
std::cout << asRectangle->area() << std::endl;
Polygon*ppoly1=新矩形(4,5);
自动asRectangle=静态_cast(ppoly1);

一种可能性是编译时多态性(CRTP):

模板
类多边形{
受保护的:
int宽度、高度;
公众:
多边形(inta,intb):宽度(a),高度(b){}
int area(){return static_cast(this)->area();};
};
类矩形:公共多边形{
公众:
矩形(inta,intb):多边形(a,b){}
int area(){返回宽度*高度;}
};
但请注意,这样就不能有基类指针(因为每个对象的基类都是不同的类型)



在您确实需要运行时多态性(即指向基类的指针)的情况下,虚拟调用通常是最好的解决方案,您不可能自己推出更好的解决方案(例如,用开启型getter与静态强制转换相结合的方式进行替换不仅更加丑陋,而且在许多情况下性能也更差,而动态强制转换比调用虚拟方法慢得多)。

一种可能性是编译时多态性(CRTP):

模板
类多边形{
受保护的:
int宽度、高度;
公众:
多边形(inta,intb):宽度(a),高度(b){}
int area(){return static_cast(this)->area();};
};
类矩形:公共多边形{
公众:
矩形(inta,intb):多边形(a,b){}
int area(){返回宽度*高度;}
};
但请注意,这样就不能有基类指针(因为每个对象的基类都是不同的类型)



在您确实需要运行时多态性(即指向基类的指针)的情况下,虚拟调用通常是最好的解决方案,您不可能自己推出更好的解决方案(例如,用开关打开型getter与静态强制转换相结合的方式进行替换不仅更加丑陋,而且在许多情况下性能也更差,而动态强制转换比调用虚拟方法慢得多).

只有将其转换回
矩形*
静态
/
动态
时,您才能实现自己的vtable并手动查找适当的函数。但是,您不太可能从
虚拟
中获得任何好处。只有将其转换回
矩形*
静态/
dynamic
\u cast
好吧,你可以实现自己的vtable并手动查找合适的函数。但是,你不太可能从
virtual
中获得任何好处。那么如果我真的这样做了,
virtual
的基本含义是什么呢?那么
virtual
I的基本含义是什么呢如果我真的这样做了?值得注意的是,如果
ppoly1
指向的对象不是
矩形
,这会导致未定义的行为。@Peter hm是的,还有更多值得注意的。例如,我怀疑首先避免将函数虚拟化是否有意义。因此我只是指问题中给出的示例同意,在这种情况下,避免将函数变为虚拟函数是没有意义的。用替代解决方案承认更明显的缺陷并没有坏处——给出未定义的行为是一个相当可靠的陷阱。值得注意的是,如果
ppoly1
指向一个不是
矩形的对象ode>,这会导致未定义的行为。@Peter hm是的,还有更多值得注意的地方。例如,我怀疑首先避免将函数虚拟化是否有意义。因此,我只参考了问题中给出的示例。我同意在这种情况下避免将函数虚拟化是没有意义的。我承认其他解决方案存在更明显的缺陷并没有什么坏处,而给出未定义的行为是一个相当可靠的缺陷。