简体   繁体   中英

C++ Inlining of virtually inherited functions

Okay, this is more a request for clarification of how a feature of C++ works than an answer of if it can. I'll start by explaining the problem I was having because the immediate answer would be that it isn't a very good class design.

I have a class which was shaping up to be an unmaintainable blob of if statements; when I tried to turn it into a composite I began being more confused about getting the deep copies to work than I was with the original blob, as well as general small object allocation problems. So instead I began looking for a way to split the blob into several classes that the compiler would be able to convert back into the original blob.

In the following code I know that super::get_x() in foo_b and foo_c are inlinable--from other stack overflow questions--but I'm not sure if super::get_z() in foo_c is. And would the calls at the end to f.get_x() , f.get_y() , and f.get_z() be virtual function calls because it's not explicit, and it doesn't know if foo has a subclass or not, or would they be inlinable because it, in fact, doesn't?

namespace PRIVATE {

class foo_a 
{
    int x, y, z;
public:
    foo_a(int X, int Y, int Z)
    {
        x = X; y = Y; z = Z;
    }
    virtual ~foo_a() { }

    virtual void update() { };

    virtual int get_x() const { return x; } 
    virtual int get_y() const { return y; }
    virtual int get_z() const { return z; }
};

class foo_b : public virtual foo_a 
{
typedef foo_a super;
    unsigned char c_0,c_1,c_2, mod;

public:
    foo_b(int X, int Y, int Z) : foo_a(X, Y, Z)
    {
        c_0 = c_1 = c_2 = mod = 0;
    }
    virtual ~foo_b() { }

    void activate_b()
    {
        c_2 = c_1;
        c_1 = c_0;
        c_0 = 5;

        mod = c_0? 1 + (c_1? 1 + (c_2? 1 : 0) : 0) : 0;
    }

    virtual void update()
    {
        super::update();

        if(c_0) { --c_0; mod = 1;
        if(c_1) { --c_1; mod = 2;
        if(c_2) { --c_2; mod = 3; }}};
    }
    virtual int get_x() const { return super::get_x() + mod; };
    virtual int get_y() const { return super::get_y() - mod; };
};

class foo_c : public virtual foo_b 
{
typedef foo_b super;
    bool active;

public:
    foo_c(int X, int Y, int Z) : foo_b(X, Y, Z)
    {
        active = false;
    }
    virtual ~foo_c() { }

    bool activate_c(bool X) { return (active = X); }

    virtual int get_x() const 
    { 
        int t = super::get_x();
        return active? t % 8 : t;
    }
    virtual int get_z() const 
    { 
        int t = super::get_z();
        return active? t % 8 : t;
    }
};

}

class foo : public virtual PRIVATE::foo_c 
{
public:
    foo(int X, int Y, int Z) : PRIVATE::foo_c(X, Y, Z) { }
    virtual ~foo() { }
};


int main(int argc, const char * argv[])
{
    foo * f = new foo(4, 6, 8);
    f->activate_b();
    f->get_x();
    f->get_y();
    f->get_z();

    delete f;

    return 0;
}

Check out the C++ FAQ :

Therefore the only time an inline virtual call can be inlined is when the compiler knows the "exact class" of the object which is the target of the virtual function call. This can happen only when the compiler has an actual object rather than a pointer or reference to an object. Ie, either with a local object, a global/static object, or a fully contained object inside a composite.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM