多态 多重继承 接口实现 虚方法不要用内联实现

这样不行,没有成员函数的实现:

#include <iostream>
using namespace std;

class Base1 {
public:
    virtual void b1();
};

class Base2 {
public:
    virtual void b2();
};

class Base :public Base1, public Base2 {
public:
    void b1() override { cout << "b1 call\n"; }
    void b2()override { cout << "b2 call\n"; }
};

 

1,加上实现就可以:等于做了基类的实现模范

没有把虚函数实现直接放在头文件的申明里面,是因为chrome规范不让!!!

大部分情况如果申明和实现不在一起,需要分开定义。

这说明一定要有Base1,Base2的实现。只有派生类有实现也不行!

 

这有个毛病就是在大的工程里面,如果不同模块中有类实现了这个接口,导致每个模块都需要有这个接口的实现。否则编译不通过。   即每个模块都要有下面的接口实现代码。这个实现需要分散在不同的模块,最后小模块要合并到一起。竟然编译通过了。

可能编译器找到一个实现后,屏蔽或者就不去查找其他实现了。


void Base1::b1() {
    cout << "nnn b1 call\n";
}
void Base2::b2() {
    cout << "nnn b2 call\n";
}

 

2,或者 将接口 Base1,Base2 定义成虚函数,便可以:

class Base1 {
public:
    virtual void b1()=0;
};

class Base2 {
public:
    virtual void b2()=0;
};

 

完整示例:


#include <iostream>
using namespace std;

class Base1 {
public:
    virtual void b1();
};

class Base2 {
public:
    virtual void b2();
};

class Base :public Base1, public Base2 {
public:
    void b1() override { cout << "b1 call\n"; }
    void b2()override { cout << "b2 call\n"; }
};

int main() {
    //指针
    Base bb;
    Base* b = &(bb);
    Base1* f1 = (Base1*)b;
    f1->b1();

    Base2* f2 = (Base2*)b;
    f2->b2();

    //用引用
    Base1& bbb = bb;
    bbb.b1();

}

 

将Base1接口强制转成 Base2,这样是不行地:

奇怪,即使base1接口类没有b2函数,强制转成Base2后,还是可以调用b2(),但实际还是跑的b1().

Base bb;
    Base* b = &(bb);
    Base1* f1 = (Base1*)b;
    f1->b1();

    Base2* f2 = (Base2*)f1;//这里f1是Base1的
    f2->b2();//还是执行的 b1函数

改成这样可以,先转回具体实现类base,再转成抽象类Base1:

    Base* ori = (Base*)f1;
    Base2* f2 = (Base2*)ori;
    f2->b2();

 

Virtual Method Out-of-lining

Virtual methods are almost never inlined in practice. Because of this, methods on a base class will be emitted in each translation unit that allocates the object or any subclasses that don't override that method. This is usually not a major gain, unless you have a wide class hierarchy in which case it can be a big win (http://codereview.chromium.org/5741001/). Since virtual methods will almost never be inlined anyway (because they'll need to go through vtable dispatch), there are almost no downsides.

If you get the error:

  • virtual methods with non-empty bodies shouldn't be declared inline

It's because you wrote something like this:

class BaseClass {

public:

virtual void ThisOneIsOK() {}

virtual bool ButWeDrawTheLineAtMethodsWithRealImplementation() { return false; }

};

And can be fixed by out of lining the method that does work:

class BaseClass {

public:

virtual void ThisIsHandledByTheCompiler() {}

virtual bool AndThisOneIsDefinedInTheImplementation();

};

posted @ 2023-01-10 15:54  Bigben  阅读(63)  评论(0)    收藏  举报