例如,我有两个班
class Foo;
class Bar;
class Foo {
const Bar &m_bar;
...
};
class Bar {
const Foo &m_foo;
...
};
Run Code Online (Sandbox Code Playgroud)
让我们foo为对象Foo和bar为对象Bar.有什么办法(正常或"黑客")创建/初始化foo和bar其成员m_bar,并m_foo会互相引用(我的意思foo.m_bar是bar和bar.m_foo是"富")?
允许添加任何成员,Foo并Bar为其添加父项,以使其成为模板等.
c++ initialization circular-dependency circular-reference member-initialization
在具有多个成员的类的成员初始化期间,似乎希望能够捕获由任何特定成员初始化程序生成的异常,以包装在额外的上下文中以便重新抛出,但是函数 try 块的语法没有出现为了适应这一点。
#include <stdexcept>
#include <string>
#include <sstream>
using namespace std::literals::string_literals;
[[noreturn]]
int thrower() { throw std::runtime_error("unconditional throw"s); }
int nonThrower() { return 3; }
class C {
int x;
int y;
public:
C();
};
class XError : public std::runtime_error {
public:
XError(const std::string& what) : std::runtime_error((std::stringstream() << "xerror: "s << what).str()) {};
};
class YError : public std::runtime_error {
public:
YError(const std::string& what) : std::runtime_error((std::stringstream() << "yerror: "s << what).str()) {};
};
C::C() try:
x(nonThrower()),
y(thrower()) {}
catch(const …Run Code Online (Sandbox Code Playgroud) 我正在使用Xcode 4.4与山狮.我似乎无法理解为什么模板中的非静态成员初始化会为变量调用移动构造函数.反正有没有克服这个错误?
示例代码:
#include <iostream>
#include <atomic>
//
// This class can compile
//
class Working
{
public:
int GetValue() { return value_; }
private:
std::atomic<int> value_{0};
};
//
// This class cannot compile
//
template <typename Ty1>
class NotWorking
{
public:
int GetValue() { return value_; }
private:
std::atomic<int> value_{0}; // <---- error here
};
int main(int argc, const char * argv[])
{
Working working;
NotWorking<int> not_working;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Xcode 4.4和Clang抛出该行中的错误说:
"Copying member subobject of type 'std::atomic<int>' invokes …Run Code Online (Sandbox Code Playgroud) 我使用这个非常简单的类而不使用任何继承.
class A
{
int a;
int b;
public:
A(int x, int y) { a = x; b = y;}
A() :A(0,0){};
~A(){};
} ;
int main ()
{
A a1, a2(5, 7) ;
}
Run Code Online (Sandbox Code Playgroud)
我收到这个错误.
错误C2614:'A':非法成员初始化:'A'不是基础或成员
SO上也有类似的问题,但它们与继承有关.有人可以解释原因以及标准对此有何看法?
编辑:
如果有人在C++ 11中详细说明了转发构造函数和这个特性,那会更好.
除了'var'(参见我在这里的另一篇文章)之外,我真正喜欢C#的一个原因是我可以声明,然后使用大括号初始化类的成员,就像这样......
var reallyLongFooVarName = new ReallyLongFooClassName(){
Name = "I'm an instance of Foo",
ID = 23 };
Run Code Online (Sandbox Code Playgroud)
甚至在一条线上,像这样......
var longFooVarName = new ReallyLongFooClassName(){ Name = "I'm an instance of Foo", ID = 23 };
Run Code Online (Sandbox Code Playgroud)
这将创建一个ReallyLongFooClassName实例,然后设置其成员'Name'和'ID'.
这个编译成同样的东西,就像你输入这个......
ReallyLongFooClassName reallyLongFooVarName = new ReallyLongFooClassName();
reallyLongFooVarName.Name = "I'm an instance of Foo";
reallyLongFooVarName.ID = 23;
Run Code Online (Sandbox Code Playgroud)
那么Objective-C/C++有什么东西等同于C#的成员括号初始化吗?
注意:感谢我的另一篇文章,我已经知道'auto'是Objective-C++中的'var'等价物,但Objective-C没有任何这样的等价,这是一种耻辱.再次,请在此处查看我的其他帖子以获取更多信息.)
我知道写初始化器.这完全是一个不同的节拍.我在上面演示的技术在C#中使用属性的setter,或者直接设置成员变量而不必编写构造函数(它们等同于Objective-C的'init'成员.)必须编写init成员强制你必须预先指定您要设置的内容.成员大括号初始化允许您以任何您想要的顺序指定属性/成员变量的任意组合.同样,它只是一次编写多行代码的语法糖.它实际上并没有改变课程.
下面的代码给出正确的输出,如果我声明变量i和j,喜欢int i, j;
class A
{
int i, j;
public:
A(int val) : i(val), j(i + 1)
{
cout<<i<<endl<<j<<endl;
}
};
Run Code Online (Sandbox Code Playgroud)
但是,如果我声明变量i和j一样int j, i;.然后j打印垃圾值.
class A
{
int j, i;
public:
A(int val) : i(val), j(i + 1)
{
cout<<i<<endl<<j<<endl;
}
};
Run Code Online (Sandbox Code Playgroud)
那么,它取决于变量声明的顺序吗?
考虑一下代码:
#include <atomic>
#include <iostream>
struct stru {
int a{};
int b{};
};
int main() {
std::atomic<stru> as;
auto s = as.load();
std::cout << s.a << ' ' << s.b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
请注意,尽管stru具有默认成员初始值设定项,但它仍然符合自C++ 14以来的聚合类型.std::atomic有一个普通的默认构造函数.根据标准,成员as应该初始化为零吗?clang 6.0.0不会这样做(见这里),而gcc 7.2.0似乎是这样(见这里).
可能重复:
C++初始化列表
成员初始化和类中的直接初始化有什么区别?这个类中定义的两个构造函数有什么区别?
class A
{
public:
int x;
int y;
A(int a, int b) : x(a), y(b)
{}
A(int a, int b)
{
x = a;
y = b;
}
};
Run Code Online (Sandbox Code Playgroud) 我有一个函数f返回一对类的对象A和B:
auto f() -> std::pair<A,B>;
Run Code Online (Sandbox Code Playgroud)
此外,我有一个班级C,其中有A和B作为成员:
class C {
public:
C();
private:
A a;
B b;
};
Run Code Online (Sandbox Code Playgroud)
在 的构造函数中C,我想使用成员初始化器列表并使用以下输出进行初始化f:
C(): a(f().first), b(f().second) {}
Run Code Online (Sandbox Code Playgroud)
虽然这会调用f两次,但它是一个相当复杂的函数。有没有办法使用成员初始值设定项列表来实现此目的,而无需调用f两次?遗憾的是,内部结构C无法更改。
这是我的代码/命名空间:
namespace myNamespace {
enum MyType {
ASD1,
ASD2,
ASD3
};
struct MyClass {
MyType mMyType;
MyClass(MyType myType = MyType::ASD1) : mMyType(myType) {
}
};
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我在另一个结构中尝试此代码:
struct X
{
myNamespace::MyClass *pMyClass1 = new myNamespace::MyClass(myNamespace::MyType::ASD2);
};
Run Code Online (Sandbox Code Playgroud)
它完美地工作,但是如果我尝试这样做:
struct X
{
myNamespace::MyClass mMyClass1(myNamespace::MyType::ASD2);
};
Run Code Online (Sandbox Code Playgroud)
它说'myNamespace::MyType::ASD2' is not a type。
既然已经声明过了,为什么呢?