构造函数不能是虚函数。但有时候确实需要能传递一个指向基类对象的指针,并且有已创建的派生类对象的拷贝。通常在类内部创建一个Clone()方法,并设置为虚函数。

//Listing 12.11 Virtual copy constructor
#include <iostream>
using namespace std; class Mammal
{
public:
Mammal():itsAge() { cout << "Mammal constructor...\n"; }
virtual ~Mammal() { cout << "Mammal destructor...\n"; }
Mammal (const Mammal & rhs);
virtual void Speak() const { 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())
{
cout << "Mammal Copy Constructor...\n";
} class Dog : public Mammal
{
public:
Dog() { cout << "Dog constructor...\n"; }
virtual ~Dog() { cout << "Dog destructor...\n"; }
Dog (const Dog & rhs);
void Speak()const { cout << "Woof!\n"; }
virtual Mammal* Clone() { return new Dog(*this); } // 这里!
}; Dog::Dog(const Dog & rhs):
Mammal(rhs)
{
cout << "Dog copy constructor...\n";
} class Cat : public Mammal
{
public:
Cat() { cout << "Cat constructor...\n"; }
~Cat() { cout << "Cat destructor...\n"; }
Cat (const Cat &);
void Speak()const { cout << "Meow!\n"; }
virtual Mammal* Clone() { return new Cat(*this); }
}; Cat::Cat(const Cat & rhs):
Mammal(rhs)
{
cout << "Cat copy constructor...\n";
} enum ANIMALS { MAMMAL, DOG, CAT};
const int NumAnimalTypes = ;
int main()
{
Mammal *theArray[NumAnimalTypes];
Mammal* ptr;
int choice, i;
for ( i = ; i<NumAnimalTypes; i++)
{
cout << "(1)dog (2)cat (3)Mammal: ";
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=;i<NumAnimalTypes;i++)
{
theArray[i]->Speak();
OtherArray[i] = theArray[i]->Clone();
}
for (i=;i<NumAnimalTypes;i++)
OtherArray[i]->Speak();
return ;
}

输出结果:

(1)dog (2)cat (3)Mammal: 3
Mammal constructor...
Woof!
Mammal Copy Constructor...
Dog copy constructor...
Meow!
Mammal Copy Constructor...
Cat copy constructor...
Mammal speak!
Mammal Copy Constructor...
Woof!
Meow!
Mammal speak!

C++虚复制构造函数,设置Clone()方法返回基类指针,并设置为虚函数的更多相关文章

  1. 虚析构函数? vptr? 指针偏移?多态数组? delete 基类指针 内存泄漏?崩溃?

    五条基本规则: 1.如果基类已经插入了vptr, 则派生类将继承和重用该vptr.vptr(一般在对象内存模型的顶部)必须随着对象类型的变化而不断地改变它的指向,以保证其值和当前对象的实际类型是一致的 ...

  2. 【转载】 C++多继承中重写不同基类中相同原型的虚函数

    本篇随笔为转载,原文地址:C++多继承中重写不同基类中相同原型的虚函数. 在C++多继承体系当中,在派生类中可以重写不同基类中的虚函数.下面就是一个例子: class CBaseA { public: ...

  3. 读书笔记 effective c++ Item 7 在多态基类中将析构函数声明为虚析构函数

    1. 继承体系中关于对象释放遇到的问题描述 1.1 手动释放 关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: class TimeKeepe ...

  4. C++基础知识 基类指针、虚函数、多态性、纯虚函数、虚析构

    一.基类指针.派生类指针 父类指针可以new一个子类对象 二.虚函数 有没有一个解决方法,使我们只定义一个对象指针,就可以调用父类,以及各个子类的同名函数? 有解决方案,这个对象指针必须是一个父类类型 ...

  5. C++基类的析构函数定义为虚函数的原因

    1:每个析构函数只会清理自己的成员(成员函数前没有virtual).2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类 ...

  6. C++的派生类构造函数是否要带上基类构造函数

    //public:Student(int s_age):People(s_age) //C++的派生类构造函数后面是否带上基类构造函数,取决于基类构造函数是否需要传入参数,如果要参数,就一定带上:不需 ...

  7. 不要在基类析构函数中调用纯虚函数,否则运行时会报错“pure virtual method called”

    如上. 这是因为:delete派生类对象时,先调用派生类的析构函数,然后再调用基类的析构函数:此时如果调用纯虚函数的话,派生类的对象已经被破坏了,所以会报错. http://www.cnblogs.c ...

  8. Field的getModifiers()方法返回int类型值表示该字段的修饰符

    其中,该修饰符是java.lang.reflect.Modifier的静态属性. 对应表如下: PUBLIC: 1PRIVATE: 2PROTECTED: 4STATIC: 8FINAL: 16SYN ...

  9. Effective Java 第三版——13. 谨慎地重写 clone 方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. URAL Formula 1 ——插头DP

    [题目分析] 一直听说这是插头DP入门题目. 难到爆炸. 写了2h,各种大常数,ural垫底. [代码] #include <cstdio> #include <cstring> ...

  2. [luoguP2495] [SDOI2011]消耗战(DP + 虚树)

    传送门 明显虚树. 别的题解里都是这样说的. 先不考虑虚树,假设只有一组询问,该如何dp? f[u]表示把子树u中所有的有资源的节点都切掉的最优解 如果节点u需要切掉了话,$f[u]=val[u]$ ...

  3. spring之scope作用域

    spring中,bean的作用域有五种类型:默认是单例模式,         singleton         prototype         request         session   ...

  4. 虚拟机搭建--hyper-V使用教程

    http://jingyan.baidu.com/article/4e5b3e19695d9f91901e24bb.html

  5. N皇后-位运算优化

    N皇后问题 时间限制: 5 Sec  内存限制: 128 MB 题目描述 魔法世界历史上曾经出现过一个伟大的罗马共和时期,出于权力平衡的目的,当时的政治理论家波利比奥斯指出:“事涉每个人的权利,绝不应 ...

  6. Codeforces Round #284 (Div. 2) D. Name That Tune [概率dp]

    D. Name That Tune time limit per test 1 second memory limit per test 256 megabytes input standard in ...

  7. Linux下重启就需要重新激活eth0的解决办法(ifup eth0)

    新安装linux系统,网卡不能自动激活去获取ip,每次都需要手工执行以下命令 ifup eth0 后续通过将ONBOOT=yes这句就能开机启动自动激活,就可以解决问题 vim /etc/syscon ...

  8. SPOJ 1479 +SPOJ 666 无向树最小点覆盖 ,第二题要方案数,树形dp

    题意:求一颗无向树的最小点覆盖. 本来一看是最小点覆盖,直接一下敲了二分图求最小割,TLE. 树形DP,叫的这么玄乎,本来是线性DP是线上往前\后推,而树形DP就是在树上,由叶子结点状态向根状态推. ...

  9. Java使用IText(VM模版)导出PDF,IText导出word(二)

    ===============action=========================== //退款导出word    public void exportWordTk() throws IOE ...

  10. Linux C多线程编程-线程互斥

    Linux下的多线程编程需要注意的是程序需要包含头文件pthread.h,在生成可执行文件的时候需要链接库libpthread.a或者libpthread.so. 线程创建函数: pthread_cr ...