C++--被遗弃的多重继承、经典问题

C++--被遗弃的多重继承、经典问题,第1张

概述一.被遗弃的多重继承 Q:C++中是否允许一个类继承自多个父类? 在实际的C++编译环境中,C++是支持编写多重继承的代码 1.一个子类可以拥有多个父类 2.子类拥有所有父类的成员变量 3.子类继承所有父类的成员函数 4.子类对象可以当作任意父类对象使用 多重继承的语法规则 但是在多重继承中会存在许多问题 Q:多重继承得到的对象可能拥有不同的地址 代码示例 #include <iostream> 一.被遗弃的多重继承

Q:C++中是否允许一个类继承自多个父类?
在实际的C++编译环境中,C++是支持编写多重继承的代码
1.一个子类可以拥有多个父类
2.子类拥有所有父类的成员变量
3.子类继承所有父类的成员函数
4.子类对象可以当作任意父类对象使用
多重继承的语法规则


但是在多重继承中会存在许多问题
Q:多重继承得到的对象可能拥有不同的地址
代码示例

#include <iostream>#include <string>using namespace std;class BaseA{    int ma;public:    BaseA(int a)    {        ma = a;    }    int getA()    {        return ma;    }};class BaseB{    int mb;public:    BaseB(int b)    {        mb = b;    }    int getB()    {        return mb;    }};class Derived : public BaseA,public BaseB//拥有两个父类{    int mc;public:    Derived(int a,int b,int c) : BaseA(a),BaseB(b)    {        mc = c;    }    int getC()    {        return mc;    }    voID print()    {        cout << "ma = " << getA() << ","             << "mb = " << getB() << ","             << "mc = " << mc << endl;    }};int main(){    cout << "sizeof(Derived) = " << sizeof(Derived) << endl;       Derived d(1,2,3);    d.print();    cout << "d.getA() = " << d.getA() << endl;    cout << "d.getB() = " << d.getB() << endl;    cout << "d.getC() = " << d.getC() << endl;    cout << endl;    //两个父类指针指向同一个对象    BaseA* pa = &d;    BaseB* pb = &d;    cout << "pa->getA() = " << pa->getA() << endl;    cout << "pb->getB() = " << pb->getB() << endl;    cout << endl;    voID* paa = pa;    voID* pbb = pb;    if( paa == pbb )    {        cout << "Pointer to the same object!" << endl;     }    else    {        cout << "Error" << endl;    }    cout << "pa = " << pa << endl;    cout << "pb = " << pb << endl;    cout << "paa = " << paa << endl;    cout << "pbb = " << pbb << endl;     return 0;}

运行结果


我们可以看到在条件判断语句中,paa与pbb指向的是同一个对象,按理说应该打印相同时的语句,可是却打印错误,从接下来的地址打印结果是不一样的,这就造成了多重继承的问题--同一个对象取地址之后进行初始化,但是pa与pb打印的结果却不同


Q:多重继承可能产生冗余的成员


代码实现

#include <iostream>#include <string>using namespace std;class People{    string m_name;    int m_age;public:    People(string name,int age)    {        m_name = name;        m_age = age;    }    voID print()    {        cout << "name = " << m_name << ","             << "Age = " << m_age << endl;    }};class Teacher : virtual public People{public:    Teacher(string name,int age) : People(name,age)    {    }};class Student : virtual public People{public:    Student(string name,age)    {    }};class Doctor : public Teacher,public Student{public:    Doctor(string name,int age) : Teacher(name,age),Student(name,People(name,age)    {    }};int main(){    Doctor d("Delphi",33);    d.print();    return 0;}


由运行结果可以知道,在进行print时出错,这是因为Doctor由于继承,会有两个打印的函数,所以通过作用域分辨符进行改正
由于冗余,打印的结果可能不一样


当多重继承关系出现闭合时将产生暑假冗余的问题
解决方案:虚继承

二.经典问题分析

一.关于动态内存分配
Q:new和malloc的区别?delete和free的区别?
A.new关键字与malloc函数的区别
1.new关键字是C++的一部分,malloc是由C库提供的函数
2.new以具体类型为单位进行内存分配,malloc以字节为单位进行内存分配
3.new在申请内存空间时可进行初始化,malloc仅根据需要申请定量的内存空间
代码示例

#include <iostream>#include <string>#include <cstdlib>using namespace std;class Test{    int* mp;public:    test()    {        cout << "Test::test()" << endl;        mp = new int(100);        cout << *mp << endl;    }    ~test()    {        delete mp;        cout << "~Test::test()" << endl;    }};int main(){    Test* pn = new Test;    Test* pm = (Test*)malloc(sizeof(Test));    delete pn;    free(pm);    return 0;}

运行结果


关于动态内存分配
new和malloc的区别
1.new在所有C++编译器中都能被支持,malloc在某些系统开发中是不能调用的
2.new能够触发析构函数的调用,malloc仅分配需要的内存空间
3.对象的创建只能使用new,malloc不适合面向对象开发
delete和free的区别
1.delete在所有C++编译器中都被支持,free在某些系统开发中是不能调用的
2.delete能够触发析构函数的调用,free仅归还之前的分配空间
3.对象的销毁只能使用delete,free不适合面向对象的开发

B.关于虚函数
Q:构造函数是否可以成为虚函数?析构函数是否可以成为虚函数?
1.构造函数不可能成为虚函数--在构造函数执行结束后,虚函数表指针才会被正确的初始化
2.析构函数可以成为虚函数--建议在设计类时将析构函数声明为虚函数

Q:构造函数中是否可以发生多态?析构函数是否可以发生多态?
1.构造函数中不可能发生多态行为--在构造函数执行时,虚函数表指针未被正确初始化
2.析构函数在不可能发生多态行为--在析构函数执行时,虚函数表指针已经被销毁
C.关于继承中的强制类型转换
1.dynamic_cast是与继承相关的类型转换关键字,并且要求相关的类中必须有虚函数
2.用于直接或者间接继承关系的指针之间


编译器会检查dynamic_cast的使用是否正确,类型转换的结果只可能在运行的阶段才能得到
代码示例

#include <iostream>#include <string>using namespace std;class Base{public:    Base()    {        cout << "Base::Base()" << endl;    }    virtual ~Base()//析构虚函数    {        cout << "Base::~Base()" << endl;    }};class Derived : public Base{};int main(){    Base* p = new Derived;//指向的是子类对象    Derived* pd = dynamic_cast<Derived*>(p);//强制转换    cout<<"pd="<<pd<<endl;    if( pd != NulL )    {        cout << "pd = " << pd << endl;    }    else    {        cout << "Cast error!" << endl;    }    delete p;    return 0;}

将其修改之后的打印结果比较


我们可以知道不能将子类指针对象指向父类,产生的对象时无效的

总结

以上是内存溢出为你收集整理的C++--被遗弃的多重继承、经典问题全部内容,希望文章能够帮你解决C++--被遗弃的多重继承、经典问题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1228657.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存