c++初始化列表功能:无需初始化成员即可调用函数
C++ initializer list capabilities: call functions without initializing member?
这是一个关于c++初始化列表语法的问题。
是否有可能从初始化列表调用函数,而不将它们作为成员对象构造函数的参数?
下面列出的代码示例来自于工作中的类似情况。
的
- 成员变量接受指向单例对象的指针作为构造函数论点。
- 成员变量由包含它的类的构造函数中的初始化列表构造。
- 在包含类被构造之前,单例没有被创建。
#include <iostream>
#define LOG { std::cout << __PRETTY_FUNCTION__ << std::endl; }
namespace
{
template <class T>
class SingletonService
{
public:
static T* Instance() { LOG; return mpT; }
static void InstallInstance(T* pT) { LOG; mpT = pT; }
static void DeleteInstance() { if (mpT) delete mpT; }
protected:
static T* mpT;
};
template <class T>
T* SingletonService<T>::mpT = NULL;
class OneOfMe
{
public:
OneOfMe() { LOG; };
virtual ~OneOfMe() { };
};
class Container
{
public:
Container(OneOfMe* pObj) { LOG; /* Do something with pObj */ }
virtual ~Container() { }
};
int GenerateNum()
{
return 42;
}
class Baz
{
public:
Baz(int num) : mNum(num) { LOG; }
virtual ~Baz() { }
protected:
int mNum;
};
class Bar
{
public:
Bar() : mBaz(GenerateNum()) { LOG; } // Perfectly OK to call function that is argument to member object's non-default ctor.
virtual ~Bar() { };
protected:
Baz mBaz;
};
class Foo
{
public:
Foo()
: SingletonService<OneOfMe>::InstallInstance(new OneOfMe) // Compile error
, mContainer(SingletonService<OneOfMe>::Instance()) { }
virtual ~Foo() { };
protected:
Container mContainer;
};
}
int main(int argc, char* argv[])
{
LOG;
Bar bar;
SingletonService<OneOfMe>::InstallInstance(new OneOfMe); // This works.
Container container(SingletonService<OneOfMe>::Instance()); // And this works.
SingletonService<OneOfMe>::DeleteInstance();
return 0;
}
编译错误
>g++ main.cpp
main.cpp: In constructor ‘<unnamed>::Foo::Foo()’:
main.cpp:45: error: expected class-name before ‘(’ token
main.cpp:45: error: no matching function for call to
‘<unnamed>::Container::Container()’
main.cpp:37: note: candidates are:
<unnamed>::Container::Container(<unnamed>::OneOfMe*)
main.cpp:35: note:
<unnamed>::Container::Container(const<unnamed>::Container&)
main.cpp:45: error: expected ‘{’ before ‘(’ token
在语法上是否可能从类构造函数的初始化列表调用函数,而不作为成员对象的非默认构造函数的实参?
这个问题是出于学术好奇心。我知道至少有一种解决方案是在创建包含类之前实例化单例。
可以使用逗号操作符
在你的例子中
class Foo
{
public:
Foo()
: mContainer((SingletonService<OneOfMe>::InstallInstance(new OneOfMe),
SingletonService<OneOfMe>::Instance()))
{}
virtual ~Foo();
protected:
Container mContainer;
};
请注意两个表达式周围的附加括号,否则它们将被解释为两个参数而不是一个参数。
解决这个问题的另一种方法是返回InstallInstance()
的单例,例如
template <class T>
class SingletonService {
public:
static T *InstallInstance(T *pT) { LOG; return mpT = pT; }
};
和
class Foo {
public:
Foo()
: mContainer(SingletonService<OneOfMe>::InstallInstance(new OneOfMe)) {}
virtual ~Foo();
protected:
Container mContainer;
};
是否有可能从初始化列表调用函数,而不将它们作为成员对象构造函数的参数?
像这样的东西可能会按预期工作:
void f() {}
struct S {
S(): i{(f(), 0)} {}
int i;
};
int main() {
S s;
}
基本思想是依赖逗号操作符。在这种情况下,函数返回的值(如果有)将被丢弃,而不用于初始化成员。
当然,我们仍然利用数据成员存在的事实,所以它可能不是您所要寻找的。
如果您想完全摆脱数据成员,您可以使用委托构造函数做类似的事情,如下面的示例所示:
void f() {}
class S {
S(int) {}
public:
S(): S{(f(), 0)} {}
};
int main() {
S s{};
}
不管被调用函数的返回类型是什么。通过逗号操作符,int
值用作标记,将调用分派给正确的编译器,然后将其丢弃。
相关文章:
- 正在初始化函数指针的constexpr数组
- 我应该在C++中使用构造函数还是初始化函数
- 使用 extern const 初始化函数
- 初始化函数中的静态变量,而不是在文件开始时
- 如何初始化函数中指针数组的大小
- 正在初始化初始化函数中的静态类成员
- call_once初始化函数
- SWIG + CMAKE:缺少初始化函数
- 如何创建在 c++ 中只读取一次的初始化函数
- 类内的强制初始化函数
- 使用元编程在编译时初始化函数数组
- 数组初始化函数:将数组作为指针传递:C++
- 从nodejs模块初始化函数报告失败
- 导入错误:动态模块未定义初始化函数
- 大括号初始化函数指针数组:从 'void (*(*)())()' 到 'void (*)()' 的转换无效
- 奇怪的行为,用 int 初始化函数指针
- 使用 init_seg 调用初始化函数
- 正在初始化函数内部的std::数组
- 初始化函数内部的指针.它是如何工作的
- JNI初始化函数以及缓存类和字段