我有一个带有const
成员的类,还有一个构造函数调用另一个构造函数,并且填充了额外的值。通常我可以使用冒号初始值设定项,但函数很复杂(printf
/ sprintf
- 喜欢)并且要求我在堆栈上使用变量,所以我必须在构造函数的主体中执行此操作并使用assign *this
到新对象。但当然这是无效的,因为我的成员变量是const
。
class A
{
public:
A(int b) : b(b), c(0), d(0) // required because const
{
int newC = 0;
int newD = 0;
myfunc(b, &newC, &newD);
*this = A(b, newC, newD); // invalid because members are const
// "cannot define the implicit default assignment operator for 'A', because non-static const member 'b' can't use default assignment operator"
// or, sometimes,
// "error: overload resolution selected implicitly-deleted copy assignment operator"
};
A(int b, int c, int d) : b(b), c(c), d(d) { };
const int b;
const int c;
const int d;
};
A a(0);
(我没有明确删除赋值运算符。)我声明成员const因为我希望它们是公共的,但不是可变的。
是否有一些规范的方法来解决这个问题,而不使用可怕的演员和强制覆盖成员' const
岬?什么是最好的解决方案?
答案 0 :(得分:2)
如何制作辅助功能:
class A
{
static int initializor(int b) { int n; myfunc(b, &n); return n; }
public:
explicit A(int b_) : b(b_), c(initializor(b_)) { }
A(int b_, int c_) : b(b_), c(c_) { }
// ... as before ...
};
答案 1 :(得分:2)
您可以添加参数类并使用C ++ 11构造函数委派或基类:
struct parameters {
int b; int c; int d;
parameters(int b): b(b), c(), d() {
myfunc(b, &c, &d);
}
};
// constructor delegation
class A {
public:
A(int b): A(parameters(b)) { }
A(parameters p): b(p.b), c(p.c), d(p.d) { }
};
// base/wrapper
class ABase {
ABase(parameters p): b(p.b), c(p.c), d(p.d) { }
};
class A: public ABase {
public:
A(int b): ABase(parameters(b)) { }
};
答案 2 :(得分:1)
我更喜欢Kerrek SB's answer,但在您的情况下,您可能无法为每个成员轻松制作单独的初始化函数。
在这种情况下,另一种解决方案是将成员移动到基类,并使用具有非const成员的帮助程序类初始化该基类。您的初始化代码将移动到辅助类的构造函数,并且可以毫无问题地进行分配。
class A_init
{
public:
A_init(int b)
{
// do whatever you like with c and d:
c = ...;
d = ...;
}
int c; // Note: non-const
int d; // Note: non-const
};
class A_base
{
public:
A_base(int b, A_init init) : b(b), c(init.c), d(init.d) {}
A_base(int b, int c, int d) : b(b), c(c), d(d) {}
const int b;
const int c;
const int d;
};
class A : public A_base
{
public:
A(int b) : A_base(b, A_init(b)) {}
A(int b, int c, int d) : A_base(b, c, d) {}
};
如果想要限制对A_init
的访问权限,可以切换为私有,并声明A
朋友。
答案 3 :(得分:0)
在哪里放置myfunc
的结果,以便可以从不同的mem-initializers设置和使用它?在默认参数中怎么样?
class A
{
private:
struct InitData;
public:
A(int b, InitData data=InitData());
A(int b, int c, int d) : b(b), c(c), d(d) { };
const int b;
const int c;
const int d;
};
struct A::InitData
{
int setup(int b);
int c;
int d;
};
inline int A::InitData::setup(int b)
{
myfunc(b, &c, &d);
return b;
}
inline A::A(int b_, InitData data)
: b(data.setup(b_)),
c(data.c),
d(data.d) {}
A a(0);
由于组合类型是私密的并且没有转换,因此不小心使用它或滥用它的风险很小。