C++ 面向对象常见问题

发布于:2022-07-17 ⋅ 阅读:(288) ⋅ 点赞:(0)


1. 面向对象的三大特征

2. 简书多态实现原理



demo1:早绑定

#include <iostream>

using namespace std;

class Base {
public:
    void func() {
        cout << "Base::func" << endl;
    }
};

class Drive : public Base {
public:
    void func() {
        cout << "Drive::func" << endl;
    }
};

int main() {
    Base *pbase1 = new Base();
    Base *pbase2 = new Drive();
    pbase1->func();
    pbase2->func();
    return 0;
}

运行结果

Base::func
Base::func

demo2:晚绑定

#include <iostream>

using namespace std;

class Base {
public:
    virtual void func() {
        cout << "Base::func" << endl;
    }
};

class Drive : public Base {
public:
    void func() {
        cout << "Drive::func" << endl;
    }
};

int main() {
    Base *pbase1 = new Base();
    Base *pbase2 = new Drive();
    pbase1->func();
    pbase2->func();
    return 0;
}

运行结果

Base::func
Drive::func

demo3:晚绑定原理

#include <iostream>

using namespace std;

class Base {
public:
    virtual void func() {
        cout << "Base::func" << endl;
    }
};

class Drive : public Base {
public:
    void func() {
        cout << "Drive::func" << endl;
    }
};

int main() {
    typedef void (*Func)(void);
    Base *pbase1 = new Base();
    Base *pbase2 = new Drive();
    long * vptr1 = (long *)*(long *)pbase1;
    Func f1 = (Func)vptr1[0];
    f1();
    long * vptr2 = (long *)*(long *)pbase2;
    Func f2 = (Func)vptr2[0];
    f2();
    // pbase1->func();
    // pbase2->func();
    return 0;
}

运行结果

Base::func
Drive::func

3. 怎样解决菱形继承


demo1

#include <iostream>

using namespace std;

class A {
public:
    void func1() {}
    void func2() {}
    int num;
};

class B1 : public A {
public:
    void func1() {}
};

class B2 : public A {
public:
    void func2() {}
};

class C : public B1, public B2 {

};

int main() {
    C c{};
    c.B1::num = 1;
    c.B2::num = 2;
    cout << "c.B1::num " << c.B1::num << " c.B2::num " << c.B2::num << endl;
    return 0;
}

运行结果:
会造成二义性

c.B1::num 1 c.B2::num 2

demo2:
如何解决菱形继承?带上virtual关键字

#include <iostream>

using namespace std;

class A {
public:
    void func1() {}
    void func2() {}
    int num;
};

class B1 : virtual public A {
public:
    void func1() {}
};

class B2 : virtual public A {
public:
    void func2() {}
};

class C : public B1, public B2 {

};

int main() {
    C c{};
    c.B1::num = 1;
    c.B2::num = 2;
    cout << "c.B1::num " << c.B1::num << " c.B2::num " << c.B2::num << endl;
    return 0;
}

运行结果

c.B1::num 2 c.B2::num 2

打印类的继承关系和虚表结构。
GCC7.x 以前使用选项:-fdump-class-hierarchy
GCC8及以后使用选项:-fdump-lang-class

  • 未使用虚继承类的继承关系和虚表结构 。可以看出两个A的地址不一样。
    在这里插入图片描述

  • 使用虚继承类的继承关系和虚表结构 。可以看出两个A的地址一样。B1 B2均会指向相同的虚表,反向查找A的地址。
    在这里插入图片描述

4. C++ 11中function lambda bind之间的关系


demo1:

#include <functional>
#include <iostream>
#include <algorithm>

using namespace std;

void hello(int count) {
    cout << "hello world: " << count << endl;
};

class StaticFunc {
public: 
    static void hello(int count) {
        cout << "StaticFunc::hello world: " << count <<endl;
    }
};

class Hello {
public:
    void operator() (int count) {
        i += count;
        cout << "Hello::hello world: " << i << endl;
    }
    
    void operator() (int a, int b) {
        cout << "Hello::hello world: a + b = " << a + b << endl;
    }
    int i = 0;
};

class CHello {
public:
    void hello(int count) {
        cout << "CHello::hello world: " << count <<endl;
    }
};

class LambdaHello {
public:
    LambdaHello(int _i) : i(_i) {}
    void operator() (int count) {
        i ++;
        cout << "LambdaHello::hello world: " << count << " i = " << i << endl;
    }
private:
    int i;
};

class BindHello {
public:
    BindHello(function<void(int)> _fn, int _count) : fn(_fn), count(_count) {}
    void operator()() {
        fn(count);
    }
private:
    function<void(int)> fn;
    int count;

};

class BindCHello {
public:
    typedef void (CHello::*Fn)(int);   
    BindCHello(Fn _fn, CHello *_c) : fn(_fn), c(_c) {}
    void operator() (int count) {
        (c->*fn)(count);
    } 
private:
    Fn fn;
    CHello *c;
};

int main() {
    function<void(int)> f_hello1 = hello;
    f_hello1(1);
    function<void(int)> f_hello2 = &hello;
    f_hello2(1);
    function<void(int)> f_hello3 = &StaticFunc::hello;
    f_hello3(2); 
    function<void(int)> f_hello4 = Hello();
    f_hello4(4);
    f_hello4(4); // 可以通过成员变量i 来存储状态

    function<void(int, int)> f_hello5 = Hello();
    f_hello5(5, 6);

    function<void(CHello *, int)> f_hello6 = &CHello::hello; //保存类的成员函数 
    CHello c;
    f_hello6(&c, 7);

    int i = 0;
    auto f_hello7 = [i](int count) mutable -> void {
        i ++;
        cout << "lambda::hello world: " << count << " i = " << i << endl;
    }; // 创建了一个闭包 
    f_hello7(8);
    cout << " i = " << i << endl; // i依然为0 

    auto f_hello8 = [&i](int count) -> void {
        i ++;
        cout << "lambda::hello world: " << count << " i = " << i << endl;
    };  
    f_hello8(8);
    cout << " i = " << i << endl; // i的值改变为1

    auto f_hello9 = LambdaHello(i);
    f_hello9(9);

    auto f_hello10 = bind(&hello, 10);
    f_hello10();

    // 绑定类成员函数
    auto f_hello11 = bind(&CHello::hello, &c, 11);
    f_hello11();
    // 提供占位符
    auto f_hello12 = bind(&CHello::hello, &c, placeholders::_1);
    f_hello12(1000);

    auto f_hello13 = BindHello(&hello, 10);
    f_hello13();

    auto f_hello14 = BindCHello(&CHello::hello, &c);
    f_hello14(10000);
    return 0;
} 

运行结果:

hello world: 1
hello world: 1
StaticFunc::hello world: 2
Hello::hello world: 4
Hello::hello world: 8
Hello::hello world: a + b = 11
CHello::hello world: 7
lambda::hello world: 8 i = 1
 i = 0
lambda::hello world: 8 i = 1
 i = 1
LambdaHello::hello world: 9 i = 2
hello world: 10
CHello::hello world: 11
CHello::hello world: 1000
hello world: 10
CHello::hello world: 10000

5. 继承下的构造函数和析构函数的执行顺序


demo1

#include <iostream>

using namespace std;

class Base1 {
public:
    Base1() {
        cout << "Base1 construction" << endl;
    }
    ~Base1() {
        cout << "Base1 desstruction" << endl;
    }
};

class Base {
public:
    Base() {
        cout << "Base construction" << endl;
    }
    ~Base() {
        cout << "Base desstruction" << endl;
    }
private:
    Base1 b1;
};


class Drive1 : public Base {
public:
    Drive1() {
        cout << "Drive1 construction" << endl;
    }
    ~Drive1() {
        cout << "Drive1 desstruction" << endl;
    }
};

class Drive : public Base {
public:
    Drive() {
        cout << "Drive construction" << endl;
    }
    ~Drive() {
        cout << "Drive desstruction" << endl;
    }
private:
    Drive1 d1;
};

// =======================================
class MDrive1 {
public:
    MDrive1() {
        cout << "MDrive1 construction" << endl;
    }
    ~MDrive1() {
        cout << "MDrive1 desstruction" << endl;
    }
};

class MDrive2 {
public:
    MDrive2() {
        cout << "MDrive2 construction" << endl;
    }
    ~MDrive2() {
        cout << "MDrive2 desstruction" << endl;
    }
};

class MBase1 {
public:
    MBase1() {
        cout << "MBase1 construction" << endl;
    }
    ~MBase1() {
        cout << "MBase1 desstruction" << endl;
    }
};

class MBase2 {
public:
    MBase2() {
        cout << "MBase2 construction" << endl;
    }
    ~MBase2() {
        cout << "MBase2 desstruction" << endl;
    }
};



class MDrive : public MBase1, public MBase2 {
public:
    MDrive() {
        cout << "MDrive construction" << endl;
    }
    ~MDrive() {
        cout << "MDrive desstruction" << endl;
    }
private:
    MDrive1 md1;
    MDrive2 md2;    
};

int main() {
    Drive d;
    cout << "-----------------" << endl;
    MDrive md;
    return 0;
}

运行结果:

Base1 construction
Base construction
Base1 construction
Base construction
Drive1 construction
Drive construction
-----------------
MBase1 construction
MBase2 construction
MDrive1 construction
MDrive2 construction
MDrive construction
MDrive desstruction
MDrive2 desstruction
MDrive1 desstruction
MBase2 desstruction
MBase1 desstruction
Drive desstruction
Drive1 desstruction
Base desstruction
Base1 desstruction
Base desstruction
Base1 desstruction

6. 虚函数表和虚函数表指针(vptr)的创建时机

7. 虚析构函数的作用

8. 智能指针种类以及使用场景

参考

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:https://course.0voice.com/v1/course/intro?courseId=5&agentId=0

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到