C++进阶

Wesley13
• 阅读 499
//############################################################################
/*
任何时候都不要在构造函数或析构函数中调用虚函数
*/
class dog {
    public:
        string m_name;
        dog(string name) {m_name = name;  bark();}
        virtual void bark() { cout<< "Woof, I am just a dog " << m_name << endl;}
};

class yellowdog : public dog {
    public:
        yellowdog(string name) : dog(string name) {...}
        virtual void bark() { cout << "Woof, I am a yellow dog " << m_name << endl; }
};

int main ()
{
  yellowdog mydog("Bob");
}


输出:
Woof, I am just a dog Bob.

/*
在构造的过程中,所有虚函数表现为非虚函数

为什么?
基类在派生类之前构造。
所以bark()的时候,yellowdog还没有构造


为什么Java中表现不一样?

Java和C++在定义对象的生命周期上有一个基本的差异
Java: 所有成员在构造函数运行前被null初始化。生命周期在构造函数之前已经开始
C++: 构造函数负责初始化成员。生命周期在构造函数结束之后才开始

调用对象中还未被初始化的部分是继承危险的
调用对象中已经被delete的部分也是危险的
*/


/*
解决方法 1:
不使用多态,使用初始化参数来产生运行时差异
*/
class dog {
    public:
        ...
        dog(string name, string color) {m_name = name; bark(color);}
        void bark(string str) { cout<< "Woof, I am "<< str << " dog " << m_name << endl;}
};

class yellowdog : public dog {
    public:
        yellowdog(string name):dog(name, "yellow") {}
};

int main ()
{
  yellowdog mydog("Bob");
}

输出:
Woof, I am yellow dog Bob


/*
解决方法 2:
使用私有静态成员函数,不同派生类可执行不同操作
*/
class dog {
    public:
        ...
        dog(string name, string woof) {m_name = name; bark(woof);}
        dog(string name) {m_name = name; bark( getMyColor() );}
        void bark(string str) { cout<< "Woof, I am "<< str << " dog " << m_name << endl;}
    private:
        static string getMyColor() {return "just a";} 
};

class yellowdog : public dog {
    public:
        yellowdog(string name):dog(name, getMyColor()) {}
    private:
        static string getMyColor() {return "yellow";}  //Why static? 
};

int main ()
{
  yellowdog mydog("Bob");
}
OUTPUT:
Woof, I am yellow dog Bob
点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
C++ 析构函数与内存池
CPrimer书中也提到编写class时要注意copycontrol成员(拷贝构造函数,赋值操作符,析构函数,C11又多个移动构造函数)。工作时在C和C之间切换,有时就忘记了C的细节(真的好讨厌)。C析构函数与构造函数对应,构造对象时调用构造函数,析构对象时调用析构函数,于是可以在对象的析构函数中释放资
Wesley13 Wesley13
2年前
C++中基类虚析构函数的作用及其原理分析
虚析构函数的理论前提是执行完子类的析构函数,那么父类的虚构函数必然会被执行。那么当用delete释放一个父类指针所实例化的子类对象时,如果没有定义虚析构函数,那么将只会调用父类的析构函数,而不会调用子类的虚构函数,导致内存的泄漏。故: 继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。知识背景     
Wesley13 Wesley13
2年前
C++基类的析构函数定义为虚函数的原因
1:每个析构函数只会清理自己的成员(成员函数前没有virtual)。2:可能是基类的指针指向派生类的对象,当析构一个指向派生类的成员的基类指针,这时程序不知道这么办,可能会造成内存的泄露,因此此时基类的析构函数要定义为虚函数;基类指针可以指向派生类的对象(多态),如果删除该指针delete\\p,就会调用该指针指向的派生类的析构函数,而派生类
Stella981 Stella981
2年前
Boost Python官方样例(三)
导出C类(纯虚函数和虚函数)大致做法就是为class写一个warp,通过get\_override方法检测虚函数是否被重载了,如果被重载了调用重载函数,否则调用自身实现,最后导出的时候直接导出warp类,但是类名使用class,析构函数不需要导出,因为它会被自动调用纯虚函数编写C函
Wesley13 Wesley13
2年前
C++中构造函数和析构函数
构造函数定义它是一种特殊的方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。另外,一个类可以有多个构造函数,我们可以根据其参数个数的不同或参数类型的不同来区分它们(这就是构造函数的重载)特点1.构造函数的命名必须和类名完全相同;2.构造函数的功能主要用于在类的对象创建时定义
Wesley13 Wesley13
2年前
C++类有继承时,析构函数必须为虚函数
C类有继承时,析构函数必须为虚函数。如果不是虚函数,则使用时可能存在内在泄漏的问题。假设我们有这样一种继承关系:!(https://oscimg.oschina.net/oscnet/5f0452c79b70794f2e4689cffa37f5a99f1.png)如果我们以这种方式创建对象:SubClasspObj
Wesley13 Wesley13
2年前
C++构造函数调用虚函数的后果
include<iostreamclasscx{public:virtualvoidfunc(){std::cout<<"func"<<std::endl;}cx(){func();//构
Wesley13 Wesley13
2年前
C++ 什么时候调用析构函数
析构函数是在对象消亡时,自动被调用,用来释放对象占用的空间。有四种方式会调用析构函数:1.生命周期:对象生命周期结束,会调用析构函数。2.delete:调用delete,会删除指针类对象。3.包含关系:对象Dog是对象Person的成员,Person的析构函数被调用时,对象Dog的析构函数也被调用。4.
Easter79 Easter79
2年前
Thinking in C++ Notes 拷贝构造函数
1.默认拷贝构造函数不会调用构造函数,而通过位拷贝来实现。2.可以使用多个构造函数,并使用默认参数。3.小心使用默认构造函数,当属性中有指针时,会造成多次析构而产生错误Reference:http://blog.csdn.net/lwbeyond/article/details/6202256(https://www.oschina
Wesley13 Wesley13
2年前
VC++知识点整理
1.内联函数定义:定义在类体内的成员函数,即函数的函数体放在类体内特点:在调用处用内联函数体的代码来替换,用于解决程序的运行效率问题。一定要在调用之前定义,并且内联函数无法递归调用。2.构造函数与析构函数构造函数:用于为对象分配内存空间,对类的成员变量进行初始化,并执行其他内部管理操作。可以接受参