class A;
class B {
public:
B(A& a) : a(a) {}
private:
A& a;
};
/* Method 1 */
/* warning C4355: 'this' : used in base member initializer list */
/*
class A {
public:
A() : b(*this) {}
private:
B b;
};
*/
/* Method 2 */
/* But I need to manually perform memory dellocation. */
class A {
public:
A() { b = new B(*this); }
~A() { delete b; }
private:
B* b;
};
int main() {
}
Run Code Online (Sandbox Code Playgroud)
目前,当我尝试初始化B中的引用时,我正在使用方法1.但是,方法1将标记我可以理解的警告.
因此,我必须使用方法2,使用动态内存分配.
有没有更好的方法可以使用,无需手动内存分配/解除分配(好的.我知道智能指针)?
我更喜欢方法1,只是因为我对警告不满意.
Mar*_*ork 14
请注意,这是一个警告(因此危险并非违法).
编译器担心的是您正在为尚未完全初始化的对象传递指针.因此,如果指针在B类构造函数中使用,则您处于未定义的行为.
因此,如果您使用此功能,您唯一能做的就是将指针指定给成员变量(引用或指针).但是请注意对变量的赋值,因为您可能会调用隐式强制转换(我不确定这是否实际上是一个问题,但RTTI在对象完全形成之前不可用).
你想通过存储参考来实现什么?
根据您正在做的事情,一种方法可能是分解出需要的部分,A而B不是A从部件继承.
struct bar_base; // interface foo wants
struct foo
{
foo(bar_base& pX) :
mX(pX)
{}
bar_base& mX;
};
struct bar_base
{
/* whatever else */
protected:
bar_base& get_base(void)
{
// getting `this` went here; safe because bar_base is initialized
return *this;
}
};
struct bar : bar_base
{
bar(void) :
// bar_base is already initialized, so:
mX(get_base())
{}
foo mX;
};
Run Code Online (Sandbox Code Playgroud)
显然,这取决于你在做什么.这可以确保您永远不会得到未定义的行为.
但实际上,这只是警告.如果你保证永远不会this在B的构造函数中使用,那么你很好,并且可以通过这种方式使警告静音:
struct bar;
struct foo
{
foo(bar& pX) :
mX(pX)
{}
bar& mX;
};
struct bar
{
bar(void) :
mX(self())
{}
foo mX;
private:
bar& self(void)
{
// fools the warning
return *this;
}
};
Run Code Online (Sandbox Code Playgroud)
不过,请确保你知道自己在做什么.(也许它可以重新设计?)