制作对象,用va_list构造构造函数
making objects, constructor with va_list
我对va_list有问题。我在构造函数中使用了它来向我的对象获取意外数量的数据。问题代码就在那里:
#include <cstdarg>
#include <iostream>
using namespace std;
class DATA{
private:
int length;
int* tab;
public:
DATA():tab(NULL), length(0){};
DATA(int x, ...):length(x+1){
va_list ap;
va_start(ap, x);
tab=new int[length];
for(int i=0; i<length; ++i){
tab[i]=va_arg(ap, int);
}
va_end(ap);
}
void showthem()const{
if(tab!=NULL){
int x;
for(x=0; x<length-1; ++x){
cout<<tab[x]<<", ";
}
cout<<tab[x];
}
}
}
ostream & operator<<(ostream & out, const DATA & x){
x.showthem();
return out;
}
int main(){
int table [] = {5,1,2,3,4,5,6};
DATA x1(*table);
DATA x2(4,1,2,3,4,5);
cout << x1 << endl;
cout << x2 << endl;
}
当我通过编写所有参数来自然地生成对象时,这是可以的,但当我试图通过表来生成它时,这就成了问题。我在类选项卡中得到了意外的数据。
我想我做错了什么。顺便说一句,我甚至可以通过*table制作这样的对象吗?我给构造函数一些整数,所以它应该可以工作。。。
KIIV做到了。std::initializer_list
(此处链接的文档)正是OP所需要的。
忘记变量参数列表。它们允许以几种不同的方式调试难以调试的程序。例如,
DATA x2(41,2,3,4,5)
哇!错过了一个逗号,将在堆栈上读取waaaaay超出范围!或
DATA x2(5, 1,2,3,4,"I am the very model of a modern major-general...")
这将更容易发现,但仍然可以编译,因为编译器不知道或不在乎变元函数允许什么类型。
但是initializer_list<int>
只允许int
秒,而不必指定int
秒的数量。这就少了一个潜在的错误!
修复了一些明显的错误步骤,暂时忽略了房间里的大象std::vector
,我们得到了看起来像的东西
#include <initializer_list>
#include <iostream>
class DATA{
private:
int length;
int* tab;
public:
DATA(std::initializer_list<int> vals):
length(vals.size()), tab(new int[length])
{
int index = 0;
for(int val: vals){
tab[index]=val;
index++;
}
}
DATA(const DATA& src) = delete;
DATA& operator=(const DATA& src) = delete;
friend std::ostream & operator<<(std::ostream & out, const DATA & x){
if(x.tab!=NULL){
int index=0;
out<<x.tab[index];
for(index++; index < x.length; ++index){
out<<", "<<x.tab[index];
}
}
return out;
}
};
int main(){
DATA x1({1,2,3,4,5});
std::cout << x1 << std::endl;
}
注意DATA x1({1,2,3,4,5});
中的{}
大括号。这将建立列表。列表知道它有多大,所以你不必告诉函数有多少项目要来。
请注意,我已经删除了复制构造函数和赋值运算符。这是因为"三条规则"。什么是"三条规则"?阅读链接并找出答案。它将为您节省大量将来的调试工作。
这也非常容易模板化:
template <class TYPE>
class DATA{
private:
int length;
TYPE* tab;
public:
DATA(std::initializer_list<TYPE> vals):
length(vals.size()), tab(new TYPE[length])
{
int index = 0;
for(const TYPE& val: vals){
tab[index]=val;
index++;
}
}
DATA(const DATA& src) = delete;
DATA& operator=(const DATA& src) = delete;
friend std::ostream & operator<<(std::ostream & out, const DATA & x){
if(x.tab!=NULL){
int index=0;
out<<x.tab[index];
for(index++; index < x.length; ++index){
out<<", "<<x.tab[index];
}
}
return out;
}
};
int main(){
DATA<int> x1({1,2,3,4,5});
DATA<std::string> x2({"I", "am", "the", "very", "model", "of", "a", "modern", "major-general"});
std::cout << x1 << std::endl;
std::cout << x2 << std::endl;
}
相关文章:
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- std::list 模板是否需要其实例类型中的复制构造函数(或等效项)?
- 错误:没有用于初始化'List<double>::node'的匹配构造函数
- 'list::list'命名构造函数,而不是类型
- 使用 boost 将 std::list 传递给构造函数,list_of不编译
- std::list 的默认构造函数可以<int>抛出吗?
- std::list<std::unique_ptr>:空初始值设定项列表与默认构造函数
- 以vector、list或map为成员的类需要复制构造函数
- 为什么std::list中的单参数构造函数定义为显式