Можно ли устранить этот конструктор базового класса? - PullRequest
2 голосов
/ 12 октября 2011

Есть ли способ устранить явный вызов конструктора в Foo и каким-то образом назначить Bar :: len размер любого из подклассов Bar?

class Bar
{
    size_t len_;

    Bar(size_t len) : len_(len) { }
};

class Foo : public Bar
{    
    Foo() : Bar(sizeof(Foo)) { }
};

Ответы [ 2 ]

6 голосов
/ 12 октября 2011

Вы можете использовать «странно рекурсивный шаблон» для информирования базового класса о типе производного класса:

template <typename Derived>
class Bar
{
    size_t len_;
protected:
    Bar() : len_(sizeof(Derived)) {}
};

class Foo : public Bar<Foo>
{
};
1 голос
/ 12 октября 2011

виртуальное наследование может делать то, что вы хотите:

#include <iostream>

class Bar
{
    size_t len_;
public:
    Bar(size_t len) : len_(len) {std::cout << len << '\n';}
};

class Foo : virtual public Bar //virtual inheritance
{    
    size_t foo_bigger_than_bar;
public:
    Foo() : Bar(sizeof(Foo)) { } //Bar only called if Foo is most derived
};

class Derived2: public Foo
{    
    size_t derived2_bigger_than_foo;
public:
    Derived2() : Bar(sizeof(Derived2)), Foo() { }
    // since Foo virtually derives from Bar, we have (get) to 
    // initialize Bar ourselves.
};

int main() {
    Foo f;
    std::cout << '\n';
    Derived2 d;
}

Виртуальный базовый класс инициализируется только самым производным классом.Например, при создании Derived2 конструктор Foo будет не конструировать объект Bar, поскольку Derived2 уже построил его.Это ключ к наследованию бриллиантов, например std::fstream.
Демо здесь: http://codepad.org/HUlLB4Uq

...