为什么有人会为类提供一个空的默认构造函数?

时间:2010-12-19 08:13:01

标签: c++

class complex
{
  float x,y;
public:
  complex(){} //constructor with no arguments //what is use of giving such constructor
    complex(float z){x=y=z;}//constructor with 1 argument.
    complex(float real,float imag)
    {x=real;y=imag;}
    friend complex sum(complex,complex);
     friend void show(complex);
};

complex sum(complex c1,complex c2)
{
  complex c3;
  c3.x=c1.x+c2.x;
  c3.y=c1.y+c2.y;
  return (c3);
}

void show (complex c)
{
  cout<<c.x<<"+j"<<c.y<<"\n";
}
int main()
{
  complex p,q,r;
  p=complex(2.5,3.9);
  q=complex(1.6,2.5);
  r=sum(p,q);

  cout<<"p=";show(p);
  cout<<"q=";show(q);
  cout<<"r=";show(r);
  return 0;
}

6 个答案:

答案 0 :(得分:22)

当您声明一个没有任何构造函数的类时,编译器会提供一个默认构造函数(按需),默认初始化成员。 (请注意,float等内置函数的默认初始化不起作用。但是,一旦为类定义了任何构造函数,就不再自动提供默认构造函数。因此,如果您仍想要一个,则必须定义自己的默认构造函数。

答案 1 :(得分:11)

这是@user470379's answer

的经过编码和更正的版本

考虑空类:

class complex
{
    float x,y;
};

编译器实际上为您生成了几个函数,即使它们未被声明。编译器生成的函数使类真正看起来像这样:

class complex
{
    float x,y;
public:
    complex(); //Compiler generated functions
    complex(const complex&);
    complex& operator=(const complex&);
    ~complex();
};

现在,您将学习复杂的类,然后使用float添加构造函数。执行此操作时,告诉C ++您不希望编译器提供默认构造函数:

class complex
{
    float x,y;
public:
    // complex(); //No longer generated
    //Don't forget explicit here unless you want implicit conversions
    //from `float`
    explicit complex(float z) {x=y=z;} //User defined constructor
    /////////////////////////////////////////////////////////
    //Compiler generated functions
    complex(const complex&);  //Note copy constructor and copy assignment
                              //operator are still generated.
    complex& operator=(const complex&);
    ~complex();
};

现在,每当有人想要complex时,他们必须提供float参数。例如,以下代码现在是非法的:

int main()
{
    complex c; //ERROR! No default constructor available.
    complex g(4.2f); //Ok; float parameter specified.
}

如果您希望用户能够在不提供complex参数的情况下构建float,则必须显式创建构造函数:

class complex
{
    float x,y;
public:
    complex() {} //Allow default construction of `complex` objects.
    //Don't forget explicit here unless you want implicit conversions
    //from `float`
    explicit complex(float z) {x=y=z;}
    ////////////////////////////////////////////////////////
    complex(const complex&);  //Compiler generated functions
    complex& operator=(const complex&);
    ~complex();
};

现在,用户可以随意在任何地方默认构建complex对象。

答案 2 :(得分:2)

因为有些程序员没有将他们的习惯升级到现代标准。

回到旧C天(C-99之前),必须在块的顶部声明变量,因此声明和初始化经常被分开。

在现代C ++中,几乎没有理由不在同一语句中声明和初始化。

因此,它应该是一个例外,而不是提供默认构造函数的规则。

答案 3 :(得分:1)

虽然我同意这样一个事实,即如果对它们没有规范意义,默认构造函数应该不受欢迎(复数应该有一个默认构造函数,使它们为零,模仿内置类型语义),有几个场景它们是强制性的。相当多的标准库构造要求默认的可构造对象,尤其是迭代器和容器的值类型(至少对于某些方法:例如resize)。

有时,您可能希望对象(或标准强制要求)具有“null”状态,该状态只能由默认构造函数访问。然后你必须写safe bool idioms,使用智能指针和pimpl惯用语等。这可能是好的,也可能不是。

我同意,将无效状态的复杂性(以及它们可能导致的错误)添加到不需要它们的对象上并不是一个好习惯,但有时候,你不得不这样做。

对于记录,复杂的类应该如下:

struct complex
{
    // Allow default initialization, and standard embedding
    // of real numbers in complex numbers
    complex(float real = 0., float imag = 0.) 
        : real(real), imag(imag) 
    {}

    float real, imag; // no need for privacy here
};

// Operators are defined outside the class
complex operator+(complex x, complex y) 
{
    return complex(x.real + y.real, x.imag + y.imag);
}

// etc

std::ostream& operator<<(std::ostream& os, complex x)
{
    return os << x.real << " + i" << x.imag;
}

请注意,由于complex是POD类型,您甚至应该能够执行complex x = { 2., 3. };并在静态数组中为它们进行零初始化。

答案 4 :(得分:0)

使用C ++标准库通常要求您的类具有无参数构造函数(如:vector<complex> vc(6);)。

创建堆栈分配(complex arcmpl[20];)或动态分配(complex * dynarcmplx = new complex[n];)的数组以及调用no-arg构造函数。

如前所述,如果你为你的类定义任何构造函数,你就没有(编译器生成的no-arg)“默认构造函数”,在这种情况下,如果你想写上面提到的东西,你应该提供你自己的无参数构造函数。

答案 5 :(得分:0)

在您不希望在整个程序中使用该类的对象的情况下,有必要提供一个空的默认构造函数( private )。

例如下面给出的类将使用编译器生成的默认空构造函数作为 public member 。结果,您可以创建此类的对象。

class test1
{
public:
int a;
};
int main()
{
test1 var; //compiles without an error.
}

但是,如果要阻止任何人构造该类的对象,则可以添加一个空的构造函数作为 private member 。例如。

class test2
{
test2(){}
public:
int a;
};

int main()
{
test2 var; // This will give an error
}
  

abc.cpp:在函数``主main()''中:abc.cpp:10:9:错误:   “ test2 :: test2()”在此上下文中是私有的test2 var; // 这个   会给出一个错误            ^ ~~ abc.cpp:3:3:注意:此处声明为私有test2(){} ^ ~~~~

如果尝试运行上述程序,则会出现错误,因为从设计上来说'test2'类不应包含对象。