2.9 C++使用默认参数的构造函数

参考:http://www.weixueyuan.net/view/6341.html

总结:

  默认参数的构造函数,其默认参数必须置于参数列表的结尾。

  设计类的构造函数的时候最好不要同时是用构造函数的重载和带参数的构造函数。

我们可以想象一个这样的场景:某一天书店整理库存,发现了一些非常老的书,为了尽快清空库存,店主想了一下,决定开展一个大甩卖活动,所有的这些书全部以五美元的价格出售。此时如果需要尽快将这些书的信息录入到书店的书单中,为了方便,我们可以在book类中添加一个带默认参数的构造函数。

[例1] 默认带参构造函数示例:

#include<iostream>
using namespace std;

class book
{
public:
    book(){}
    book(char* a, double p = 5.0);
    void display();
private:
    double price;
    char * title;
};

book::book(char* a, double p)  //在定义函数的时候可以不指定默认参数
{
    title = a;
    price = p;
}

void book::display()
{
    cout<<"The price of "<<title<<" is $"<<price<<endl;
}

int main()
{
    book Harry("Harry Potter", 49.9);
    Harry.display();
    book Gone("Gone with the Wind");
    Gone.display();
    return 0;
}

在本例中,book类中的带参构造函数 book(char* a, double p = 5.0); 将价格设置为5.0,如此一来p就被设置成为一个默认参数,如果在创建对象的时候,没有传递实参给该参数p,则该参数会被默认设置为5.0。

在例1的主函数中我们可以看到Harry对象创建时传递了两个实参"Harry potter"和49.9,而Gone 对象则只是传递了一个实参"Gone with the Wind"用于初始化title,此时price就会被用默认参数初始化为5.0。

程序运行结果如下:
The price of Harry Potter is $49.9
The price of Gone with the Wind is $5.0

需要说明的是带默认参数的构造函数,其默认参数必须置于参数列表的结尾。如果例1中带参构造函数 book(char* a, double p = 5.0); 被声明成 book(double p = 5.0, char* a); 则是无法通过编译的,因为默认参数不在参数列表的结尾。

虽然带参数的构造函数会给我们初始化带来一定便利,但糟糕的是它也会给构造函数的调用带来歧义。

[例2] 默认带参构造函数所带来的歧义:

  1. #include<iostream>
  2. using namespace std;
  3. class book
  4. {
  5. public:
  6. book(){}
  7. book(char* a, double p = 5.0);
  8. book(char *a);
  9. void setprice(double a);
  10. double getprice();
  11. void settitle(char* a);
  12. char * gettitle();
  13. void display();
  14. private:
  15. double price;
  16. char * title;
  17. };
  18. book::book(char* a, double p) //在定义函数的时候可以不指定默认参数
  19. {
  20. title = a;
  21. price = p;
  22. }
  23. book::book(char *a)
  24. {
  25. title = a;
  26. }
  27. void book::display()
  28. {
  29. cout<<"The price of "<<title<<" is $"<<price<<endl;
  30. }
  31. int main()
  32. {
  33. book Harry("Harry potter", 49.9);
  34. Harry.display();
  35. book Gone("Gone with the Wind"); //compile error
  36. Gone.display();
  37. return 0;
  38. }

在本例中有三个构造函数,一个是默认构造函数,两个带参构造函数,其中一个为带有默认参数的构造函数。

在主函数中,通过book类创建Harry对象没有问题,此时创建对象只能调用book(char* a, double p = 5.0);构造函数。创建Gone对象时则有问题了,此时我们创建对象有两个与之匹配的构造函数可以调用,分别是book(char *a);和book(char* a, double p = 5.0);,此时该调用哪一个呢?无法得知,编译器只能报错了。

出现这种情况我们只能极力去避免了,通常而言,在设计类的构造函数的时候最好不要同时是用构造函数的重载和带参数的构造函数,以避免上述问题。

时间: 2024-08-10 17:21:24

2.9 C++使用默认参数的构造函数的相关文章

使用默认参数的构造函数 .

1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #include<set> 9 #include<stack> 10 #include<string> 1

C++:构造函数的默认参数知识拓展

和普通函数一样,构造函数中参数的值既可以通过实参传递,也可以指定为某些默认值,即如果用户不指定实参值,编译系统就使形参取默认值. 例9.3的问题也可以使用包含默认参数的构造函数来处理. [例9.4]将例9.3程序中的构造函数改用含默认值的参数,长.宽.高的默认值均为10. #include <iostream> using namespace std; class Box { public : Box(int h=10,int w=10,int len=10); //在声明构造函数时指定默认参

类的六个默认成员函数-&gt;构造函数

在C++中当你创建一个空类时,编译器会默认声明一个default构造函数,copy构造函数,一个copy assignment操作符,一个析构函数.注意,编译器只声明,只有当这些函数被调用时,他们才会被创建. 举个栗子,当你写下 class Empty() {}; 实际上在编译器中为你实现了这样的代码 class Empty { Empty(){} Empty(const Empty& rhs){} ~Empty(){} Empty& operator=(const Empty&

拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

 1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: #include<iostream> //如果声明已经定义,边不会生成 class classA { private: int a; int b; public: //拷贝构造的规则,有两种方式实现初始化 //1.一个是通过在后面:a(x),b(y)的方式实现初始化 //2.第二种初始化的方式是直

C++构造函数的自动调用(调用一个父类的构造函数,有显性调用最好,否则就默认调用无参数的构造函数)——哲学思想:不调用怎么初始化父类的成员数据和VMT?

我总是记不住构造函数的特点,关键还是没有领会那个哲学思想:父类的构造函数一方面要初始化它自己的成员数据,另一方面也要建立它自己的VMT呀!心里默念一百遍:一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数,一定调用父类构造函数VMT,一定调用父类构造函数VMT,一定调用父类构造函数VMT,一定调用父类构造函数VMT,一定调用父类构造函数VMT,一定调用父类构造函数VMT,一定调用父类构造函数VM

C++ 构造函数的默认参数

默认参数需要写在函数声明位置,函数体定义时不需要写默认参数. (√) int func(int=1); int func(int a){}; (×) int func(int); int func(int a=1){}; (×) int func(int=1); int func(int a=1){}; 默认参数必须从参数列表的右端开始. (√) int boxVolume( int length, int width = 1, int height = 1 ); (×) int boxVolu

【C/C++学院】0819-/类的成员函数与const-mutable /构造与析构/拷贝构造deletedefault以及深浅拷贝/静态成员函数成员变量类在内存的存储默认参数/友元类以及友元函数

类的成员函数与const-mutable 成员函数 Fushu.h #pragma once #include <iostream> class fushu { public: int x; int y; public: fushu(); ~fushu(); void show(); inline void showall(int x, int y);//显式内联 void setxy(int x, int y);//编译器优化,默认隐式内联 void show(int x, int y);

【spring教程之二】spring注入xml中带参数的构造函数

1.续上文,如果想在注入bean文件的时候,传入参数到构造函数中.主要需要修改的就是spring.xml配置文件中的配置方法. <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-insta

【ThinkingInC++】38、选择重载还是默认参数

头文件 /** * 书本:[ThinkingInC++] * 功能:选择重载还是默认参数,头文件 * 时间:2014年9月6日14:54:28 * 作者:cutter_point */ #ifndef MEM_H_INCLUDED #define MEM_H_INCLUDED typedef unsigned char byte; class Mem { byte* mem; int size; void ensureMinSize(int minSize); //成员函数来增加内存块的大小 p