How can I simulate interfaces in C++?

后端 未结 9 2129
时光说笑
时光说笑 2020-12-04 19:22

Since C++ lacks the interface feature of Java and C#, what is the preferred way to simulate interfaces in C++ classes? My guess would be multiple inheritance o

9条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-04 20:27

    "What are the implications in terms of memory overhead/performance?"

    Usually none except those of using virtual calls at all, although nothing much is guaranteed by the standard in terms of performance.

    On memory overhead, the "empty base class" optimization explicitly permits the compiler to layout structures such that adding a base class which has no data members does not increase the size of your objects. I think you're unlikely to have to deal with a compiler which does not do this, but I could be wrong.

    Adding the first virtual member function to a class usually increases objects by the size of a pointer, compared with if they had no virtual member functions. Adding further virtual member functions makes no additional difference. Adding virtual base classes might make a further difference, but you don't need that for what you're talking about.

    Adding multiple base classes with virtual member functions probably means that in effect you only get the empty base class optimisation once, because in a typical implementation the object will need multiple vtable pointers. So if you need multiple interfaces on each class, you may be adding to the size of the objects.

    On performance, a virtual function call has a tiny bit more overhead than a non-virtual function call, and more importantly you can assume that it generally (always?) won't be inlined. Adding an empty base class doesn't usually add any code to construction or destruction, because the empty base constructor and destructor can be inlined into the derived class constructor/destructor code.

    There are tricks you can use to avoid virtual functions if you want explicit interfaces, but you don't need dynamic polymorphism. However, if you're trying to emulate Java then I assume that's not the case.

    Example code:

    #include 
    
    // A is an interface
    struct A {
        virtual ~A() {};
        virtual int a(int) = 0;
    };
    
    // B is an interface
    struct B {
        virtual ~B() {};
        virtual int b(int) = 0;
    };
    
    // C has no interfaces, but does have a virtual member function
    struct C {
        ~C() {}
        int c;
        virtual int getc(int) { return c; }
    };
    
    // D has one interface
    struct D : public A {
        ~D() {}
        int d;
        int a(int) { return d; }
    };
    
    // E has two interfaces
    struct E : public A, public B{
        ~E() {}
        int e;
        int a(int) { return e; }
        int b(int) { return e; }
    };
    
    int main() {
        E e; D d; C c;
        std::cout << "A : " << sizeof(A) << "\n";
        std::cout << "B : " << sizeof(B) << "\n";
        std::cout << "C : " << sizeof(C) << "\n";
        std::cout << "D : " << sizeof(D) << "\n";
        std::cout << "E : " << sizeof(E) << "\n";
    }
    

    Output (GCC on a 32bit platform):

    A : 4
    B : 4
    C : 8
    D : 8
    E : 12
    

提交回复
热议问题