【ThinkingInC++】75、多重继承

本文探讨了C++中的多重继承和虚基类的概念。通过具体示例代码展示了多重继承时可能遇到的问题及如何使用虚基类来解决二义性问题。此外,还介绍了虚基类初始化的过程和规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第九章 多重继承

9.2 接口继承

Intertfacees.cpp

/**

* 书本:【ThinkingInC++】

* 功能:接口继承Interfaces.cpp

* 时间:2014年10月28日20:06:31

* 作者:cutter_point

*/

 

#include <iostream>

#include <sstream>

#include <string>

 

using namespace std;

 

class Printable //抽象类

{

public:

   virtual ~Printable() {} //虚函数

   virtual void print(ostream&) const=0;   //纯虚函数

};

 

class Intable

{

public:

   virtual ~Intable() {}

   virtual int toInt() const=0;

};

 

class Stringable

{

public:

   virtual ~Stringable() {}

   virtual string toString() const=0;

};

 

class Able : public Printable, publicIntable, public Stringable

{

   int myData;

public:

   Able(int x) { myData=x; }

   void print(ostream& os) const { os<<myData; }

   int toInt() const { return myData; }

   string toString() const

    {

       ostringstream os;

       os<<myData;

       return os.str();

    }

};

 

void testPrintable(const Printable& p)

{

   p.print(cout);

   cout<<endl;

}

 

void testIntable(const Intable& n)

{

   cout<<n.toInt()+1<<endl;

}

 

void testStringable(const Stringable&s)

{

   cout<<s.toString()+"th"<<endl;

}

 

int main()

{

   Able a(7);

   testPrintable(a);

   testIntable(a);

   testStringable(a);

 

   return 0;

}


 

9.5 虚基类

 

虚拟继承的机制

实际上造成上边的二义性的根本原因是在这样的继承的特殊模式下。A这个父类分别伴随BC产生了两个拷贝。在调用拷贝中的方法时产生了矛盾。究竟是调用哪一个拷贝中的print()呢?于是,全部人都会想,要是仅仅有一个拷贝就好了,就没有矛盾了。虚拟继承就提供了这样的机制,按上面的样例,仅仅需改动BCA的继承方式,即加一个keyword virtual

class B:  virtual public A

{

    public:

        B(){cout << "B called"<< endl;}

       

    private:

           

};

class C:  virtual public A

{

    public:

        C(){cout << "C called"<< endl;}

           private:

           

};


这样就相当于说。在没有A类的拷贝时就构造一个,假设已经有了,就用已经有的那一个,这样一来,拷贝仅仅有一份了。二义性消除了。

 

static_cast 和 dynamic_cast

 

http://www.cnblogs.com/chio/archive/2007/07/18/822389.html

 

dynamic_cast主要用于类层次间的上行转换和下行转换。还能够用于类之间的交叉转换。



在类层次间进行上行转换时。dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

 

子对象的初始化顺序遵循例如以下规则:

1)  全部虚基类子对象,依照他们在类定义中出现的位置,重上到下、从左到右初始化

2)  然后非虚基类按通常顺序初始化

3)  全部的成员对象按声明的顺序初始化

4)  完整的对象的构造函数运行

 

前面讲过,为了初始化基类的子对象。派生类的构造函数要调用基类的构造函数。

对于虚基类来讲,因为派生类的对象中仅仅有一个虚基类子对象。为保证虚基类子对象仅仅被初始化一次,这个虚基类构造函数必须仅仅被调用一次。

 

 

http://blog.youkuaiyun.com/maojudong/article/details/8169240

 

假设类继承中包含多个虚基类的实例。基类仅仅被初始化一次。

1、假设类里面有成员类,成员类的构造函数优先被调用。

2、创建派生类的对象。基类的构造函数函数优先被调用(也优先于派生类里的成员类);

3、 基类构造函数假设有多个基类则构造函数的调用顺序是某类在类派生表中出现的
顺序而不是它们在成员初始化表中的顺序。


4、成员类对象构造函数假设有多个成员类对象则构造函数的调用顺序是对象在类中
被声明的顺序而不是它们出如今成员初始化表中的顺序;


5、派生类构造函数
作为一般规则派生类构造函数应该不能直接向一个基类数据成员赋值而是把值传递
给适当的基类构造函数否则两个类的实现变成紧耦合的(tightly coupled)将更加难于
正确地改动或扩展基类的实现。

(基类设计者的责任是提供一组适当的基类构造函数)

 

 

VirtInit.cpp

//关于虚基类的初始化问题

 

/**
* 书本:【ThinkingInC++】
* 功能:关于虚基类的初始化问题
* 时间:2014年10月28日20:07:25
* 作者:cutter_point
*/

#include <iostream>
#include <string>

using namespace std;

class M
{
public:
    M(const string& s) { cout<<"M "<<s<<endl; } //每个类都有嵌入的M类型成员
};

class A
{
    M m;    //这里是一个类的组合
public:
    A(const string& s) : m("in A")
    {
        cout<<"A "<<s<<endl;    //跟踪类A的初始化
    }
    virtual ~A() { cout<<"析构A"<<endl; } //这是一个虚基类
};

class B
{
    M m;    //这里是一个类的组合
public:
    B(const string& s) : m("in B")
    {
        cout<<"B "<<s<<endl;    //跟踪类A的初始化
    }
    virtual ~B() { cout<<"析构B"<<endl; } //这是一个虚基类
};

class C
{
    M m;    //这里是一个类的组合
public:
    C(const string& s) : m("in C")
    {
        cout<<"C "<<s<<endl;    //跟踪类A的初始化
    }
    virtual ~C() { cout<<"析构C"<<endl; } //这是一个虚基类
};


class D
{
    M m;    //这里是一个类的组合
public:
    D(const string& s) : m("in D")
    {
        cout<<"D "<<s<<endl;    //跟踪类A的初始化
    }
    virtual ~D() { cout<<"析构D"<<endl; } //这是一个虚基类
};

class F : virtual public B, virtual public C, public D  //虚继承
{
    M m;
public:
    F(const string& s) : B("from F"), C("from F"), D("from F"), m("in F")
    {
        cout<<"F "<<s<<endl;
    }
};

//開始多重继承
class E : public A, virtual public B, virtual public C  //虚继承
{
    M m;
public:
    E(const string& s) : A("from E"), B("from E"), C("from E"), m("in E")
    {
        cout<<"E "<<s<<endl;
    }
};



//终于的继承E,F
class G : public E, public F
{
    M m;
public:
    //这里初始化的顺序和继承的顺序不同。看看结果,结果是按继承的顺序初始化
    G(const string& s) : B("from G"), C("from G"), F("from G"), E("from G"), m("in G")
    {
        cout<<"G "<<s<<endl;
    }
};

int main()
{
    //构造函数的调用顺序是某类在类派生表中出现的顺序

    G g("from main");

    return 0;
}


重要结论:

基类构造函数假设有多个基类则构造函数的调用顺序是某类在类派生表中出现的
顺序而不是它们在成员初始化表中的顺序。

 

内容概要:本文详细探讨了基于阻尼连续可调减振器(CDC)的半主动悬架系统的控制策略。首先建立了CDC减振器的动力学模型,验证了其阻尼特性,并通过实验确认了模型的准确性。接着,搭建了1/4车辆悬架模型,分析了不同阻尼系数对悬架性能的影响。随后,引入了PID、自适应模糊PID和模糊-PID并联三种控制策略,通过仿真比较它们的性能提升效果。研究表明,模糊-PID并联控制能最优地提升悬架综合性能,在平顺性和稳定性间取得最佳平衡。此外,还深入分析了CDC减振器的特性,优化了控制策略,并进行了系统级验证。 适用人群:从事汽车工程、机械工程及相关领域的研究人员和技术人员,尤其是对车辆悬架系统和控制策略感兴趣的读者。 使用场景及目标:①适用于研究和开发基于CDC减振器的半主动悬架系统的工程师;②帮助理解不同控制策略(如PID、模糊PID、模糊-PID并联)在悬架系统中的应用及其性能差异;③为优化车辆行驶舒适性和稳定性提供理论依据和技术支持。 其他说明:本文不仅提供了详细的数学模型和仿真代码,还通过实验数据验证了模型的准确性。对于希望深入了解CDC减振器工作原理及其控制策略的读者来说,本文是一份极具价值的参考资料。同时,文中还介绍了多种控制策略的具体实现方法及其优缺点,为后续的研究和实际应用提供了有益的借鉴。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值