将变量声明为“类”数据类型,而不调用“类”构造函数?
Posted
技术标签:
【中文标题】将变量声明为“类”数据类型,而不调用“类”构造函数?【英文标题】:Declaring a variable as a "Class" datatype, without calling the "Class" constructor? 【发布时间】:2010-01-31 09:32:02 【问题描述】:如果我只是公然遗漏了什么,请原谅我,但我正在尝试从结构和 c 过渡到类和 c++。
这就是我想要做的:
A 有一个“Checkers”类和一个“Board”类。
现在有了结构,我可以在我的“board.cpp”文件中创建一个 Checkers 数组,方法是:
Checker checkers[2][12]
(每边0和1,每块0-11)
问题在于,对于类,执行相同的声明会尝试调用“Checkers”构造函数。我收到这个错误:“错误:没有匹配函数调用‘Checker::Checker()’”
我的 Checker 构造函数处理初始化一个单独的部分(比如它在 0 或 1 侧,0-11 部分),所以我不想在那里调用它。
有没有办法避免这种情况,或者我是不是走错了路?谢谢。
编辑:或者我应该只设计构造函数来初始化一个检查器数组?您甚至可以将变量声明为类/对象的数据类型吗?
【问题讨论】:
另一种情况:“显然,我对问题的英文描述比发布编码要好”。邮政编码。用代码的上下文解释问题。 【参考方案1】:您可以创建一个默认构造函数或拥有一个Checker
指针数组,并通过在Board
的构造函数中使用适当的参数动态分配每个Checker
来初始化它们。在后一种情况下,在分配它们之前不会调用构造函数。
【讨论】:
【参考方案2】:创建一个默认构造函数。然后使用初始函数。我建议你使用 STL 向量。
【讨论】:
那么,不要在Checkers构造函数中做任何事情,稍后再初始化值? 以上建议都不好。默认构造函数不会解决问题,它会隐藏问题。它需要重新思考课堂的运作方式。向量适用于动态调整大小的数组,但大小在编译时是已知的(而不是动态分配的),因此没有理由使用向量。 使用向量有一个原因——如果你的库实现了它,你就会得到边界检查。 (假设您不想导入任何其他边界检查数组类)。但否则是的。 实际上向量(正常使用)NOT 有边界检查。您特别需要使用边界检查 API 'at(X)'。如果我们谈论的是调试模式,那么是的,向量可以有一个调试版本的 STL,它实现了边界检查,但编译器在这种情况下也可能对数组进行边界检查(如果可能的话)。 我同意 Martin 的观点——C++ 的库中可能有一些高级功能,但在很多情况下它仍然具有低级脆弱性。对向量的越界访问的结果是官方未定义的,与数组没有什么不同 - 如果你有一些东西 more 而不是 C++,你只会得到一个异常抛出,你可以得到东西也可以对普通的 C 数组执行此操作(有一个产品 称为 Boundschecker)。顺便说一句 - 这包括基于迭代器的访问 - 在典型的 C++ 实现中,向量迭代器可以很好地移出向量的边界。【参考方案3】:问题在于,对于类,执行相同的声明会尝试调用“Checkers”构造函数。我收到此错误:“错误:没有匹配函数调用‘Checker::Checker()’”
如果你为你的类定义了参数化构造函数(并且没有定义默认构造函数),编译器不会提供默认构造函数。您还必须编写默认构造函数的版本。
不要使用二维数组,而是使用向量的向量。
std::vector<std::vector<Checker> > checkers;
【讨论】:
@Downvoter:请告诉我原因。这太不可思议了,两次无缘无故投了反对票。 x-( +1 回到 0。看看好的一面,你获得了 (2 * 10) - (2 * 2) = 16 代表! 不是我。但我试图再给你一个反对票。为什么要使用向量?数组的大小是静态的,不是动态分配的。不好的建议。编写默认构造函数不会解决问题(只是隐藏它)。 @Daniel:坦率地说,我不太关心声誉(我们都在这里学习),但我不明白为什么我的回答被否决了。答案没有那么糟糕。 @Martin:大小在编译时是已知的,这很好。我只是推荐了我应该拥有的东西。数组是邪恶的,你最好知道它,就默认构造函数而言,如果他创建另一个没有参数的 Checker 对象怎么办?然后他必须定义它。:-)【参考方案4】:您正在创建一个检查器数组来表示属于每一侧的各个检查器。跳棋要求您说出跳棋在哪一侧,以及在哪一侧跳棋。
为什么你需要知道哪个检查器是哪个?如果一个玩家走出房间,并且有人交换了他的两个棋子,他会注意到吗?
您可以使用数组语法传递一个构造函数参数,如下所示:
enum Side White, Black ;
class Checker
Side side ;
public:
Checker ( Side side ) : side(side)
;
int main()
Checker white[12] = White, White, White, White, White, White, White, White, White, White, White, White, ;
Checker black[12] = Black, Black, Black, Black, Black, Black, Black, Black, Black, Black, Black, Black, ;
Checker* both[2] = white, black ;
return 0;
多个参数需要一个复制构造函数,看起来像:
Checker white[12] = Checker(White,0), Checker(White,1) ...
但我倾向于只使用几个棋子对象将棋子添加到棋盘中,而不是代表白、黑、白皇后和黑皇后,除非有很好的理由来跟踪身份。
【讨论】:
我对每个棋子都有单独的数字,因为这就是我显示棋盘并获取用户输入要移动的棋子的方式【参考方案5】:要回答这个问题,我真的需要看一下“Checker”类的定义。不过,这是一个猜测......
我认为您的 Checker 类定义了非默认构造函数,但没有默认构造函数。有一个默认的默认构造函数 IYSWIM,但是一旦您为自己定义了任何构造函数,编译器提供的隐式默认构造函数就会被禁用。
如果你有...
class Checker
public:
Checker (int p) ... ;
;
您不能根据需要使用默认构造函数...
Checker checkers[2][12];
相反,尝试...
class Checker
public:
Checker () ... ;
Checker (int p) ... ;
;
关于使用 std::vector 的建议,在这种情况下我不同意。该数组是固定大小的,因此使用 std::vector 没有任何好处 - 只有额外的复杂性和其他成本。
我的建议是保留您的 C 样式数组,但在“Board”类中将其设为私有(或至少受保护)。
【讨论】:
以上是关于将变量声明为“类”数据类型,而不调用“类”构造函数?的主要内容,如果未能解决你的问题,请参考以下文章