精华内容
下载资源
问答
  • C.45: Don't define a default constructor that only initializes data members;...C.45:不要只初始化数据成员的默认构造函数;使用类内成员初始化器 Reason(原因) Using in-class member initi...

    C.45: Don't define a default constructor that  only initializes data members; use in-class member initializers instead

    C.45:不要只初始化数据成员的默认构造函数;使用类内成员初始化器

     

     

    Reason(原因)

    Using in-class member initializers lets the compiler generate the function for you. The compiler-generated function can be more efficient.

    使用类内初始化器可以让编译器为你生成一个函数。编译器生成的函数效率更高。

     

     

    Example, bad(反面示例)

    class X1 { // BAD: doesn't use member initializers
        string s;
        int i;
    public:
        X1() :s{"default"}, i{1} { }
        // ...
    };

     

     

    Example(示例)

    class X2 {
        string s = "default";
        int i = 1;
    public:
        // use compiler-generated default constructor
        // ...
    };

     

     

    Enforcement(实施建议)

    (Simple) A default constructor should do more than just initialize member variables with constants.

    (简单)默认构造函数应该比使用常量初始化数据成员做的更多。

     

    译者注:差不多就是杀鸡焉用牛刀的意思。

     

     

     

    原文链接

    https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#c45-dont-define-a-default-constructor-that-only-initializes-data-members-use-in-class-member-initializers-instead

     


     

    觉得本文有帮助?欢迎点赞并分享给更多的人。

    阅读更多更新文章,请关注微信公众号【面向对象思考】

    展开全文
  • #include <iostream> using namespace std; ...初始化列表进行数据成员初始化 1.构造函数():属性1(值1), 属性2(值2), ... 2.数据成员含有字符数组时,不能使用初始化列表 /*************
    #include <iostream>
    
    using namespace std;
    
    
    /************************************************************************
    
    初始化列表进行数据成员初始化
    1.构造函数():属性1(值1), 属性2(值2), ...                                               
    2.数据成员含有字符数组时,不能使用初始化列表
    /************************************************************************/
    class Person{
    public:
    
    	Person(int age, char *name, string tel):m_age(age),m_tel(tel)
    	{
    		strcpy(m_name, name);
    	}
    	void get_mem_value()
    	{
    		cout<<"m_age:"<<m_age<<endl;
    		cout<<"m_name:"<<m_name<<endl;
    		cout<<"m_tel:"<<m_tel.c_str()<<endl;
    
    	}
    
    private:
    	int m_age;
    	char m_name[20];
    	string m_tel;
    };
    
    void test1()
    {
    	Person per(20, "zhangsan","13296639109");
    	per.get_mem_value();
    	
    }
    
    
    
    int main()
    {
    
    	test1();
    
    	return 0;
    }
    
    #include <iostream>
    
    using namespace std;
    
    class Animal
    {
    public:
    	//有参构造函数
        Animal(int weight,int height):m_weight(weight),m_height(height){}
    	virtual void get_data()
    	{
    		cout<<"m_weight"<<m_weight<<", m_height"<<m_height<<endl;
    	}
    
    private:
        int m_weight;
        int m_height;
    };
    
    class Dog
    {
    public:
    	/*本类中存在其他类对象作为数据成员时,若该对象类存在有参构造函数,不存在无参构造函数时,
    	 *对这个对象初始化时需要调用有参构造函数,若不使用初始化列表则会报错;		
    	*/
    	Dog(int type, int weight,int height):m_type(type),m_animal(weight,height){}
    	void get_data()
    	{
    		cout<<"m_type:"<<m_type<<endl;
    		m_animal.get_data();
    	}
    private:
        int m_type;
    	Animal m_animal;
    };
    
    
    class Cat:public Animal
    {
    public:
    	//子类构造函数初始化时,则显示调用父类有参构造函数进行初始化列表
    	Cat(int type, int weight,int height):m_type(type),Animal(weight,height){}
    private:
        int m_type;
    };
    
    int main()
    {
    	Cat ct(10, 20, 30);
    	Dog dg(40,50, 60);
    	Animal *mal = &ct;
    	
    
    	mal->get_data();
    	dg.get_data();
    	return 0;
    };
    
    展开全文
  • 1.分配内存,调用构造函数时,隐式/显示的初始化数据成员(构造函数列表的初始化方式不是按照列表的的顺序,而是按照变量声明的顺序同时初始化显隐数据成员); 2.进入构造函数后在构造函数中执行一般赋值与计算。...

    类对象的构造顺序是这样的:

    1.分配内存,调用构造函数时,隐式/显示的初始化各数据成员(构造函数列表的初始化方式不是按照列表的的顺序,而是按照变量声明的顺序同时初始化显隐数据成员);

    2.进入构造函数后在构造函数中执行一般赋值与计算。

    使用初始化列表有两个原因:

    原因1.必须这样做:

    《C++ Primer》中提到在以下三种情况下需要使用初始化成员列表:

       情况一、需要初始化的数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化); 

       情况二、需要初始化const修饰的类成员或初始化引用成员数据;

       情况三、子类初始化父类的私有成员;

     ■情况一的说明:数据成员是对象,并且这个对象只有含参数的构造函数,没有无参数的构造函数;

         如果我们有一个类成员,它本身是一个类或者是一个结构,而且这个成员它只有一个带参数的构造函数,而没有默认构造函数,这时要对这个类成员进行初始化,就必须调用这个类成员的带参数的构造函数,如果没有初始化列表,那么他将无法完成第一步,就会报错。

    例子:

    using namespace std;
    class Test
    {
    public:
        Test(int, int, int) {
            cout << "Test" << endl;
        };
    private:
        int x;
        int y;
        int z;
    };
    class Mytest
    {
    public:
        Mytest() :test(1, 2, 3) {       //初始化
            cout << "Mytest" << endl;
        };
    private:
        Test test; //声明
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
        Mytest test;
        return 0;
    }

    输出结果:

    ①   如果没有mytest():test(1,2,3){}初始化列表就会报错:

    因为Test有了显示的带参数的构造函数,那么他是无法依靠编译器生成无参构造函数的,所以没有三个int型数据,就无法创建Test的对象。Test类对象是MyTest的成员,想要初始化这个对象test,那就只能用成员初始化列表,没有其他办法将参数传递给Test类构造函数。

    ②初始化列表在构造函数执行前执行(这个可以看上面的结果,对同一个变量在初始化列表和构造函数中分别初始化,首先执行参数列表,后在函数体内赋值,后者会覆盖前者)。

     

    ■情况二的说明:对象引用或者cosnt修饰的数据成员

         情况二:当类成员中含有一个const对象时,或者是一个引用时,他们也必须要通过成员初始化列表进行初始化,因为这两种对象要在声明后马上初始化,而在构造函数中,做的是对他们的赋值,这样是不被允许的。

    例子:

    class Test
    {
    priate:
        const int a;             //const成员声明
    public:
        Test() :a(10) {}           //初始化
    };
    //或
    class Test
    {
    private:
        int &a;                        //声明
    public:
        Test(int a) :a(a) {}        //初始化
    }

    ■情况三的说明:子类初始化父类的私有成员,需要在(并且也只能在)参数初始化列表中显示调用父类的构造函数:如下:

     例子:

    class Test {
    public:
        Test() {};
        Test(int x) { int_x = x;
        std::cout << int_x << std::endl;
        };
        void show() { std::cout << int_x << std::endl; }
    private:
        int int_x;
    };
    class Mytest :public Test {
    public:
        Mytest():Test(110) 
        {
            //Test(110);            //  构造函数只能在初始化列表中被显示调用,不能在构造函数内部被显示调用
        };
    };
    int _tmain(int argc, _TCHAR* argv[])
    {
        Test *p = new Mytest();
        p->show();
        return 0;
    }

    结果:如果在构造函数内部被显示调用输出结果是:-842150451(原因是虽然调用了 Test (int x),但是直接调用构造函数产生了一个临时对象,而不是调用父类的构造函数来构造父类的私有变量,作用域只在一条语句中,所以相当于什么都没做。故而直接打印出一个随机值。);

                如果在初始化列表中被显示调用输出结果是:110

    原因2.效率要求这样做:

         类对象的构造顺序显示,进入构造函数体后,进行的是计算,是对成员变量的赋值操作,显然,赋值和初始化是不同的,这样就体现出了效率差异,如果不用成员初始化类表,那么类对自己的类成员分别进行的是一次隐式的默认构造函数的调用,和一次赋值操作符的调用,如果是类对象,这样做效率就得不到保障。

    注意:构造函数需要初始化的数据成员,不论是否显示的出现在构造函数的成员初始化列表中,都会在该处完成初始化,并且初始化的顺序和其在类中声明时的顺序是一致的,与列表的先后顺序无关,所以要特别注意,保证两者顺序一致才能真正保证其效率和准确性。

    为了说明清楚,假设有这样一个类:

    class foo
    
    {
    
     private:
    
       int a, b;
    
    };

    ①、foo(){}和foo(int i = 0){}都被认为是默认构造函数,因为后者是默认参数。两者不能同时出现。

    构造函数列表的初始化方式不是按照列表的的顺序,而是按照变量声明的顺序。比如foo里面,a在b之前,那么会先构造a再构造b。所以无论foo():a(b + 1), b(2){}还是foo():b(2),a(b+1){}都不会让a得到期望的值。

    ③构造函数列表能够对const成员初始化。比如foo里面有一个int const c;则foo(int x) : c(x){}可以让c值赋成x。

      不过需要注意的是,c必须在每个构造函数(如果有多个)都有值。

    ④在继承里面,只有初始化列表可以构造父类的private成员(通过显示调用父类的构造函数)。比如说:

    class child : public foo{};
    
    //foo里面的构造函数是这样写的:
    
    foo (int x)
    
    {
    
      a =x;
    
    }

    而在child里面写child(int x){ foo(x); }是通过不了编译的。

    只有把子类构造函数写作child(int x) : foo(x){}才可以。

    展开全文
  • c++初始化数据成员
    c++中初始化数据成员
    当我们需要给类中数据初始化的时候,该怎么做?有什么方法?有几种?
    我不敢说初始化数据成员的方法我都掌握了,我把常见的几种初始化数据成员的方法介绍下。

    一、利用构造函数初始化数据成员

    c++提供了构造函数来处理对象的初始化,在建立对象时,自动执行。
    1)利用无参的构造函数

    若使用无参数的构造函数初始化数据成员,初始化数据成员在函数体中执行,对不同的类对象都得到同一组初值。如下
    class Tan
    {
    public:
    	Tan();//无参数的构造函数初始化数据成员
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    Tan::Tan()
    {
    	weight = 10;
    	length = 20.34;
    }
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan;
    	cout<<"the area of tan is"<<tan.area()<<endl;
    
    }
    2)利用有参的构造函数

    采用带参数的构造函数时,在调用不同对象的构造函数时,从外面将不同的数据传递给构造函数,以实现不同的初始化。实参是在定义对象时给出,定义对象的一般格式为  类名  对象名(实参1,实参2,实参3,等等)
    class Tan
    {
    public:
    	Tan(float w,float le);//有参的构造函数初始化数据
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    Tan::Tan(float w,float le)
    {
    	weight = w;
    	length = le;
    }
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan1(20,3.33);
    	Tan tan2(10,5.33);
    	cout<<"the area of tan1 is"<<tan1.area()<<endl;
    	cout<<"the area of tan2 is"<<tan2.area()<<endl;
    
    }
    二、利用构造函数初始化列表初始化数据成员

    这种方法不在函数体内对数据成员初始化,而是在函数首部实现。
    class Tan
    {
    public:
    	Tan(float w,float le);
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    Tan::Tan(float w,float le):weight(w),length(le)
    {
    	
    }
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan1(20,3.33);
    	Tan tan2(10,5.33);
    	cout<<"the area of tan1 is"<<tan1.area()<<endl;
    	cout<<"the area of tan2 is"<<tan2.area()<<endl;
    
    }
    还有一种是这样的,直接在类的内部利用初始化列表初始化数据成员
    class Tan
    {
    public:
    	Tan(float w,float le):weight(w),length(le){}
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan1(20,3.33);
    	Tan tan2(10,5.33);
    	cout<<"the area of tan1 is"<<tan1.area()<<endl;
    	cout<<"the area of tan2 is"<<tan2.area()<<endl;
    
    }
    初始化列表也可以无参数
    class Tan
    {
    public:
    	Tan():weight(20),length(10){}
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan1;
    	Tan tan2;
    	cout<<"the area of tan1 is"<<tan1.area()<<endl;
    	cout<<"the area of tan2 is"<<tan2.area()<<endl;
    
    }
    成员初始化的次序就是类中定义成员的次序,与初始化列表中的顺序无关。没有默认构造函数的类类型的成员,以及const或引用类型的成员,都必须在构造函数初始化列表中进行初始化。const或引用类型的成员不能赋值,只能初始化。


    最后贴个程序大家看看它的输出结果
    class Tan
    {
    public:
    	Tan(float w = 20,float le = 3.33);//有参的构造函数初始化数据
    	float area();
    private:
    	float weight;
    	float length;
    	
    };
    Tan::Tan(float w,float le)
    {
    	weight = w;
    	length = le;
    }
    float Tan::area()
    {
    	return weight*length;
    }
    void main()
    {
    	Tan tan1;
    	Tan tan3(30,10);
    	cout<<"the area of tan1 is"<<tan1.area()<<endl;
    	cout<<"the area of tan3 is"<<tan3.area()<<endl;
    
    }



    展开全文
  • C.47: Define and initialize member variables in the order of member declarationC.47:按照成员变量声明的次序定义和初始化数据成员Reason(原因)To minimize confusion and errors. That is the order in which ...
  • 类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/显示的初始化数据... 情况一、需要初始化数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);
  • 类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/显示的初始化数据... 情况一、需要初始化数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员进行初始化);
  • C++初始化数据成员

    2014-11-26 10:13:00
    在C++初始化类的成员数据有两种方式1. 在构造函数中实现 2. 定义初始化成员列表来初始化成员数据 class point { private: int x,y; public: point(int m,int n) { x=m; y=n; } }; class ...
  • C.47: Define and initialize member variables in the ...C.47:按照成员变量声明的次序定义和初始化数据成员 Reason(原因) To minimize confusion and errors. That is the order in which the initi...
  • 转自 类对象的构造顺序是这样的: 1.分配内存,调用构造函数时,隐式/显示的初始化数据成员;... 情况一、需要初始化数据成员是对象的情况(这里包含了继承情况下,通过显示调用父类的构造函数对父类数据成员...
  • 在构造体内初始化数据成员是最常见的方法。 例如: #include using namespace std; class A { private: int i; string s; public: A(int ii,string ss){ //在构造函数体内初始化数据成员 i=ii; s=ss; ...
  • 定义构造方法用来初始化数据成员。再定义显示display方法将姓名和年龄打印出来。 在main方法中创建人类的实例然后将信息显示。 代码如下: /* * 编写Java程序用于显示人的姓名和年龄。 * 定义一个人类Person该类中...
  • 以给定对话框id为例(给某一个对话框添加对话框类,在类定义时,id已经限定) ...2 静态常量整型成员(一定是整型的吗?) static const int IDD= IDD_PENWIDTH_DLG; 适用于在类定义时,就限定了的成员
  • 定义一个学生类(Student),要求: (1)初始化数据成员数据成员(Sno,Sname,Sage); (2)通过属性装饰器定义数据成员(Sno,Sname,Sage); (3)定义特殊方法__str(self),该方法返回:这样的字符串“我叫...
  • 题目相对简单: package naizi; public class Circle { ...//私有成员及构造方法 private Point center; private int r; Circle(int rr,Point Cc){ this.r=rr; this.center=Cc; } public void showInfo(){ ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,999
精华内容 4,399
关键字:

初始化数据成员