C++如何为基类casted对象调用纯虚拟方法
C++ How are pure-virtual methods called for base-class-casted objects?
可能重复:
为什么派生类中的重写函数隐藏基类的其他重载?
嗨,
让我用这个例子来解释我的问题:
class A
{
virtual ~A() = 0 { }
A(const A&);
virtual void operator =(const A&) = 0;
}
class B : public A
{
~B();
B(const B&);
void operator =(const B&);
}
void main(void)
{
A* a = new B();
delete a; // Is ~A() called, ~B() or both ?
}
这让我提出了两个问题:
- 在对抽象基类指针使用delete时,调用哪个析构函数
- 有可能用上面的复制方法之一复制我的对象"a"吗
-
两者都被调用。
在
delete a
中,派生类析构函数~B::B
被找到并使用虚拟调度机制调用。~B::B
的实现又隐式地调用基类析构函数~A::A
。然而,此调用被实现为非虚拟普通调用,这意味着它不受~A::A
被声明为纯的事实的影响。这就是为什么仍然需要定义纯虚拟析构函数的原因。尽管语言规范不允许对纯虚拟函数进行类内定义。即使您希望它是内联的,您仍然必须在类外定义它。
-
复制
A
类型的独立对象是不可能的,因为不可能有任何抽象类型的独立的对象。请澄清你的问题。你想复制什么?复制到哪里?如果你想做这样的
B b1, b2; A *a1 = &b1, *a2 = &b2; *a1 = *a2;
并且期望最后的分配表现得好像执行了CCD_ 7。。。好吧,这是可以做到的,但这需要一些努力,并且可能/将导致非常丑陋的代码。我想说,用这种功能来加重重载的赋值运算符的负担不是一个好主意。
virtual ~A() = 0 { }
这不会编译。纯虚拟析构函数看起来像:
virtual ~A() = 0;
即便如此,也必须添加一个实现,因为所有类继承结构的析构函数在破坏对象时都会被调用。因此,如果你不实现主体,这将导致UB(或者它甚至不会编译,因为我在gcc 4.6.3中没有这样做)。
1:~B()
通过虚拟~A() = 0
调用;则CCD_ 11调用CCD_。
此外,virtual ~A() = 0 { }
是不正确的语法;您必须编写virtual ~A() = 0;
,然后在类定义之外提供inline A::~A() { }
。
2:您的代码不会编译,因为B::operator=(const B&)
不是A::operator=(const A&) = 0
的可接受覆盖;对于虚拟方法,只允许函数返回类型是协变的。
没有简单的方法可以通过复制构造函数或赋值运算符来复制多态对象,因为这样的成员必须使用双重调度(请参阅虚拟赋值运算符C++)。通常的方法是使用一个virtual A *clone() = 0
函数,该函数将返回派生类的new
实例。
1)首先调用析构函数~B(),在析构函数_A()之后,记住这是:
在构造函数已被调用的情况下,析构函数将在相反的顺序。
2) 是的,因为它是指针,所以heritage可以阻止复制(通过recopy构造)
- 是否可以使用函数指针调用虚拟析构函数?
- 为什么使用存储在虚拟方法表中的地址调用虚拟函数的函数会返回垃圾?
- 使用回调函数从构造函数调用虚拟/派生方法的替代方法?
- 使用在堆栈上创建的对象调用虚拟函数
- 如何从派生类函数中调用虚拟函数
- 从内部类的析构函数调用虚拟函数
- 使用范围解析运算符时,在构造函数中调用虚拟方法是否安全?
- 调用虚拟成员类的方法
- 为什么不调用虚拟基非默认构造函数,除非大多数派生基显式调用它们?
- 为什么在运行时调用虚拟函数时需要虚拟表
- 从C++中的虚拟析构函数调用虚拟方法
- 如何在C++中调用虚拟析构函数
- 调用虚拟函数而不通过类类型指针创建任何对象
- 通过命名成员调用虚拟与地址或引用的区别
- 从派生的指针中调用虚拟功能,而无需支付VTable价格
- 为什么我不能从铸造的字节(char)数组中调用虚拟函数
- 在基类崩溃中调用虚拟功能
- 可以通过跨二进制边界传递的对象上的接口调用虚拟函数吗?
- 调用虚拟方法的不同方法
- C++未根据需要调用虚拟方法