How to make sure a virtual method gets called just after the constructor?

I have a base class with an abstract virtual function fv() which is only implemented in derived classes. I want to make sure that the fv() of the derived classes is called in or immediately after the constructor.

However, when I call the virtual function in the constructor, I get a warning, and the code can’t be linked:

undefined reference to `A::fv()’

I also tried this:

class A{
    A() {fx()};
    virtual void fv() = 0;
    void fx(fv());
}
    
class B : public A {
    B():A();
    void fv() {};
}

int main(int argc, char **argv) {
     B::b{];
}

This code compiles, but when I run it I get:

pure virtual method called
terminate called without an active exception
Aborted

Of course, I can manually call fv() in the constructor of B, but this seems inelegant and not safe, because someone deriving a class from my A might forget to call fv() (which could lead to undefined behavior in my real code).

Is there an “automatic” way to make sure that the fv() of derived classes will be called as soon as the object is instantiated?

8

You can’t call a virtual method inside the base class constructor. The derived class object doesn’t exist yet. And there is no automatic way to call a method after a constructor.

One common way to handle this is to make the constructor(s) private so no instances can be created directly, and then write a separate factory that can create the instances. This way, every instance must be created by your factory, and the factory can do whatever it needs after calling a constructor before returning the new instance.

For example:

#include <unordered_map>
#include <functional>
#include <string>
#include <memory>

class A {
protected:
    A() { ... }

public:
    using A_ptr = std::unique_ptr<A>;
    using createFunc = std::function<A_ptr()>;

    virtual ~A() { ... }
    
    virtual void fv() = 0;
    void fx() { ... }

    static void registerCreator(const std::string& name, createFunc creator) {
        m_creators[name] = std::move(creator);
    }

    static A_ptr create(const std::string& name) {
        auto instance = m_creators.at(name)();
        instance->fv();
        return instance;
    }

private:
    static std::unordered_map<std::string, createFunc> m_creators;
};

std::unordered_map<std::string, A::createFunc> A::m_creators;
    
class B : public A {
protected:
    B() { ... }

public:
    ~B() { ... }

    void fv() override { ... }
    static A_ptr createMe() { return A_ptr(new B); }
};

class C : public B {
    C() { ... }

public:
    ~C() { ... }

    void fv() override { ... }
    static A_ptr createMe() { return A_ptr(new C); }
};

int main(int argc, char **argv) {
    A::registerCreator("B", &B::createMe);
    A::registerCreator("C", &C::createMe);

    auto b = A::create("B");
    b->fx();

    auto c = A::create("C");
    c->fx();
}

Demo

6

You can achieve this by hiding the constructors and using a factory-like method to create objects.

The only way to create objects is to use the Factory method since the B constructor is private.

The Factory method creates the object and calls the fv method.

Now, when you call the fx method you are sure the fv method has already been called.

For example:

class A{
protected:
    A() {};
public:
    virtual void fv() = 0;
    void fx(){}
};

class B: public A 
{
    B():A(){};
public:
    void fv() {};
    static B Factory()
    {
        B obj;
        obj.fv();
        return obj;
    }
};

int main(int argc, char **argv) 
{
     B b = B::Factory();
     b.fx();
}

Note that you will have to use move and copy constructors for more complex objects of B.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật