Is this pointer to a base class constructor?

I want to implement a derived class that also needs to implement an interface that has a function that the base class can call. The following gives a warning, since it is unsafe to pass this pointer to the constructor of the base class:

struct IInterface
{
    void FuncToCall() = 0;
};

struct Base
{
    Base(IInterface* inter) { m_inter = inter; }

    void SomeFunc() { inter->FuncToCall(); }

    IInterface* m_inter;
};

struct Derived : Base, IInterface
{
    Derived() : Base(this) {}

    FuncToCall() {}
};

What is the best way to do this? I need to provide an interface as an argument to the base constructor, since this is not always a dumb class, which is an interface; sometimes it can be a completely different class.

I could add a function to the base class SetInterface (IInterface * inter), but I would like to avoid this.

+3
source share
6 answers

this , . , , , .

, , factory:

struct Base
{
public:
    Base() { }

    void setInterface(IInterface* inter) { m_inter = inter; }

    void SomeFunc() { inter->FuncToCall(); }

    IInterface* m_inter;
};

struct Derived : Base, IInterface
{
private:
    Derived() : Base() {}

public:
    static Derived* createInstance() {
        Derived instance = new Derived();
        instance->setInterface(instance);
        return instance;
    }

    FuncToCall() {}
};

, Derived , , createInstance.

+4

:

struct IInterface
{
    virtual ~IInterface();
    virtual void FuncToCall() =0;
};

class Base { public: virtual ~Base(); void SomeFunc() { GetInterface().FuncToCall(); } private: virtual IInterface& GetInterface() =0; };

class Derived: public Base, public IInterface { public: private: virtual IInterface& GetInterface() { return *this; } virtual void FuncToCall(); };

+3

, ( ) , . , , Base.

, , , undefined, .

+2

:

struct IInterface
{
    void FuncToCall() = 0;
    IInterface* me() { return this; }
};

...

struct Derived : IInterface, Base
{
    Derived() : IInterface(), Base(me()) {}

    FuncToCall() {}
};

, . II , ()

+1

protected: IInterface* m_inter;

struct IInterface
{
    virtual void FuncToCall() = 0;
};

struct Base
{
    Base(IInterface* inter) { m_inter = inter; }

    void SomeFunc() { m_inter->FuncToCall(); }

protected: // or `public:` since you are using `struct`
    IInterface* m_inter;
};

struct Derived : Base, IInterface
{
  //Derived() : Base(this) {} // not good to use `this` in the initialization list
    Derived() : Base() { m_inter = static_cast<IInterface*>(this); }

    FuncToCall() {}
};
0

Which is pretty funny is that you could get away from it by initializing it later:

Derived::Derived(): Base()
{
  this->setInter(this);
}

excellent because all attributes have been initialized.

This way you do not have to change the whole design to avoid a warning.

However, if setInternothing is done thisseparately from some memory, you can access an object that you did not fully initialize (so saving a value hashcan be inconvenient).

0
source

Source: https://habr.com/ru/post/1738970/


All Articles