簡體   English   中英

這個指向基類構造函數的指針?

[英]this pointer to base class constructor?

我想實現一個派生類,它也應該實現一個接口,它有一個基類可以調用的函數。 以下是一個警告,因為將this指針傳遞給基類構造函數是不安全的:

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() {}
};

圍繞這個最好的方法是什么? 我需要提供接口作為基礎構造函數的參數,因為它並不總是作為接口的衍生類; 有時它可能是一個完全不同的類。

我可以在基類SetInterface(IInterface * inter)中添加一個函數,但我想避免這種情況。

你不應該從構造函數中發布this ,因為那時你的對象還沒有正確初始化。 但是,在這種實際情況下,它似乎是安全的,因為您只將它發布到基類,它只存儲它,並且直到稍后某個時候才會調用它,此時構造將完成。

但是,如果要刪除警告,可以使用靜態工廠方法:

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完成實例化。

您始終可以推遲接口取消引用:

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(); };

您可以執行一組有限的操作(由標准保證),並指向尚未初始化的對象,並將其存儲以供進一步使用。 編譯器可能會發出警告,因為很容易在Base濫用接收到的指針。

請注意,除了存儲之外,指針的大多數用法都是未定義的行為,但上面的代碼是正確的。

有趣的是,您可以稍后通過初始化來逃避它:

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

很好,因為所有屬性都已初始化。

這樣您就不必為了逃避警告而改變整個設計。

然而,除非setInter不會做任何this除了一些存儲,你可能訪問你沒有完全初始化(所以存儲對象hash值可以是尷尬)。

怎么樣:

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

...

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

    FuncToCall() {}
};

在我們到達Base構造函數IInterface的那一點已經初始化了,所以對me()的調用是安全的,並且沒有警告

如何使用protected: for 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() {}
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM