在C++中,在构造期间用'this'指针初始化一个类成员
我想创建一个以某种父子关系关联另一个类的类。为此,“孩子”课程需要提及其父母。在C++中,在构造期间用'this'指针初始化一个类成员
例如:
template <typename T>
class TEvent {
private: T* Owner;
public: TEvent(T* parent) : Owner(parent) {}
};
class Foo {
private: TEvent<Foo> Froozle; // see below
};
现在的问题是,我不能直接初始化Froozle
情况下,也没有使用Foo的构造函数的instanciation列表,因为this
引用是不允许存在。除了增加另一种方法setParent(T*)
(我不喜欢太多,因为这意味着我必须将TEvent<>
实例置于无效状态),有没有办法实现这一点?
在初始化列表中使用this
是可以的,只要它不用于访问任何尚未初始化的成员即可。
这是应该工作;实际上,
template<class T>
class Child {
private:
T *parent;
public:
Child(T *parent) : parent(parent) {}
};
class Parent {
private:
Child<Parent> child;
public:
Parent() : child(this) {}
};
用g ++ 4.4.5和clang ++ 2.8编译得很好。
什么是你的失败?
“将警告视为错误”的VC编译器标志和标有“错误消息”的MSDN文档标题。 :)你是完全正确的 - 它的工作原理,我只是没有看到它。非常感谢! – sunside 2010-10-23 21:52:06
从标准12.6.2/7“初始化碱和成员”(重点煤矿):
名称在 MEM-初始化的表达式列表中的构造的 范围被评估为其指定了 mem初始值设定项。
[实施例:
class X { int a; int b; int i; int j; public: const int& r; X(int i): r(a), b(i), i(i), j(this->i) {} };
初始化
X::r
指X::a
, 与 构造参数i
的值初始化X::b
,初始化X::i
与 构造参数i
的值,和 初始化X::j
的值为X::i
;这发生在每次创建class X
的 对象时。 ][注:由于MEM-初始化是 在 构造的范围进行评价,所述
this
指针可以 可以在 的MEM-初始化来指代 对象是表达式列表用于初始化。 ]
看起来很疯狂。 :D – sunside 2010-10-23 21:54:42
这是否意味着“this”仅允许在ctor的mem-initializer列表中,还是允许在ctor的主体中?我已经尝试过使用VC2010 ++中的ctor体内的“this”几次,它全部编译并运行正常,警告C4355禁用,但仅仅因为它的工作并不意味着我被允许。到目前为止,我还没有在[开放标准文档](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf)中找到任何内容,允许在该机构内部提及“this”。 – 2013-02-26 19:21:02
@DavidLee:在构造函数中,this指向正在构造的对象(就像在上面描述的初始化器列表中一样)。你可以在构造函数体内使用'this'。 – 2013-02-26 20:49:27
如果你正在寻找相应的警告,只是这样做:
class Foo
{
public:
Foo() :
Froozle(get_this())
{}
private:
Foo* get_this()
{
return this;
}
TEvent<Foo> Froozle; // see below
};
的间接足以阻止它。
heh。为什么一个方法调用没问题,但直接引用没有?傻编译:) – ephemient 2010-10-23 22:13:36
我不认为这是对你的失败,除非你有警告级别设置为4(或类似的,我假设Visual Studio),并已启用“治疗警告作为错误”。
基本上,这个警告是一件好事,因为它不会让你不小心使用this
指针,当它指向什么尚未构建。
但是,当你知道你在做什么,无论this
在初始化列表中传递,由此引发的警告和错误将会很烦人。
您可以通过装饰构造摆脱它(再次,假设的Visual Studio)(除非它在类声明的已定义 - 那么你必须装饰所有的类):
// warning C4355: 'this' : used in base member initializer list
#pragma warning (push)
#pragma warning (disable : 4355)
some_class::some_class()
: ...
{
}
#pragma warning (pop)
他说什么。只要你传递'this'的对象在构造过程中“不知道”触及它(因为这个对象'this'没有被完全构造),这样做很好,即使一些编译器(特别是VC)发出警告。 – sbi 2010-10-23 21:43:18
VC++是这里的关键。它确实有效。好像我必须强行压制那个“错误”。非常感谢! – sunside 2010-10-23 21:53:09
我希望VC++只在ctor内的“this”成员访问时发出警告。顺便说一句,谷歌:: LogMessage类在[谷歌博客](http://code.google.com/p/google-glog)存储“this”自己在mem-initializer列表ctor出于调试目的。我必须重新编译#pragma警告(4355:禁用)才能在VC2010中工作。 – 2013-02-26 19:10:29