虚拟复制构造函数
Virtual Copy Constructor
如果在每个派生类中的析构函数和Clone()
函数之前注释掉virtual
,会有什么区别吗?它们都产生相同的输出:
#include <iostream>
class Mammal
{
public:
Mammal():itsAge(1) { std::cout << "Mammal constructor...n"; }
virtual ~Mammal() { std::cout << "Mammal destructor...n"; }
Mammal (const Mammal & rhs);
virtual void Speak() const { std::cout << "Mammal speak!n"; }
virtual Mammal* Clone() { return new Mammal(*this); }
int GetAge()const { return itsAge; }
protected:
int itsAge;
};
Mammal::Mammal (const Mammal & rhs):itsAge(rhs.GetAge())
{
std::cout << "Mammal Copy Constructor...n";
}
class Dog : public Mammal
{
public:
Dog() { std::cout << "Dog constructor...n"; }
/*virtual*/ ~Dog() { std::cout << "Dog destructor...n"; }
Dog (const Dog & rhs);
void Speak()const { std::cout << "Woof!n"; }
/*virtual*/ Mammal* Clone() { return new Dog(*this); }
};
Dog::Dog(const Dog & rhs):
Mammal(rhs)
{
std::cout << "Dog copy constructor...n";
}
class Cat : public Mammal
{
public:
Cat() { std::cout << "Cat constructor...n"; }
/*virtual*/ ~Cat() { std::cout << "Cat destructor...n"; }
Cat (const Cat &);
void Speak()const { std::cout << "Meow!n"; }
/*virtual*/ Mammal* Clone() { return new Cat(*this); }
};
Cat::Cat(const Cat & rhs):
Mammal(rhs)
{
std::cout << "Cat copy constructor...n";
}
enum ANIMALS { MAMMAL, DOG, CAT};
const int NumAnimalTypes = 3;
int main()
{
Mammal *theArray[NumAnimalTypes];
Mammal* ptr;
int choice,i;
for (i = 0; i<NumAnimalTypes; i++)
{
std::cout << "(1)dog (2)cat (3)Mammal: ";
std::cin >> choice;
switch (choice)
{
case DOG:
ptr = new Dog;
break;
case CAT:
ptr = new Cat;
break;
default:
ptr = new Mammal;
break;
}
theArray[i] = ptr;
}
Mammal *OtherArray[NumAnimalTypes];
for (i=0;i<NumAnimalTypes;i++)
{
theArray[i]->Speak();
OtherArray[i] = theArray[i]->Clone();
}
for (i=0;i<NumAnimalTypes;i++)
OtherArray[i]->Speak();
return 0;
}
不,没有区别。
如果派生类继承了上层类的虚拟函数,它们将自动获得virtual
属性。即使你没有明确宣布,它们也是虚拟的。
在您展示的示例中没有任何区别。
通常,如果基类和派生类有内存分配/资源分配,那么您需要更小心地使用析构函数,并使用虚拟析构函数来调用基类清理。
考虑:
class Base
{
// some virtual methods
};
class Derived : public Base
{
~Derived()
{
// Do some important cleanup
}
}
Base *b = new Derived();
delete b;
在上面的场景中,当调用delete b时,您将调用基类的析构函数,而不调用派生类的析构因子,因此可能导致资源泄漏。
因此,在您的场景中没有区别,因为基类为这些函数声明了虚拟关键字,但是,如果您将其从基类中删除,您将遇到上面我的scneario中描述的问题。
特别是在你的情况下,打印出来的东西显然会从猫/狗/等改变。。对于哺乳动物,如果基类将没有用于克隆和复制构造函数的虚拟关键字。
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 当从函数参数中的临时值调用复制构造函数时
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 使用复制构造函数复制双精度数组
- C 无可行的构造函数复制类型的变量
- 没有可行的构造函数复制类型 'MyString' 的数组元素
- 编译时,复制构造函数/复制分配和正常功能调用优化之间是否存在任何区别
- 如何最小化调用列表构造函数(复制构造函数)的次数?
- C 11矢量构造函数复制与范围
- 我定义了一个非复制构造函数;复制构造函数还会被隐式定义吗
- 可以将构造函数复制为转换运算符
- 将基类指针的构造函数复制到子类
- C++树类:构造函数/复制/内存泄漏
- 如何制作这个在模板构造函数复制中使用类型定义的类型的模板
- 将构造函数复制为模板化的成员函数
- 绕过私有复制构造函数/复制赋值C++
- C++通过构造函数复制对象
- 复制构造函数 - 复制C++中的对象
- 将带unique_ptr的类的构造函数复制到作为成员的抽象类