c++ java类成员变量初始化必须在构造函数中初始化吗

1. 普通的变量:
&&&& 一般不考虑啥效率的情况下&可以在构造函数中进行赋值。考虑一下效率的可以再构造函数的初始化列表中进行。
&1&class&CA&
&3&public:&
&4&&&&& int&&
&5&public:&
&6&&&&& CA();&
&9&CA::CA():data(<span style="color: #)&//&#8230;&#30;&#8230;初始化列表方式&
<span style="color: #&{&
<span style="color: #&&&& //data&=&0;//&#8230;&#30;&#8230;赋值方式&
<span style="color: #&};&
2、static&静态变量:&
&&&&& static变量属于类所有,而不属于类的对象,因此不管类被实例化了多少个对象,该变量都只有一个。在这种性质上理解,有点类似于全局变量的唯一性。&
<span style="color: #&class&CA&
<span style="color: #&{&
<span style="color: #&public:&
<span style="color: #&&&&& static&int&&
<font color="#
<span style="color: #&public:&
<span style="color: #&&&& CA();&&
<span style="color: #&};&
<span style="color: #&int&CA::sum=<span style="color: #;&&&&//&#8230;&#30;&#8230;类外进行初始化&
3、const&常量变量:
&&&& const常量需要在声明的时候即初始化。因此需要在变量创建的时候进行初始化。一般采用在构造函数的初始化列表中进行。
&1&class&CA&
&3&public:&
&4&&&&&const&int&&
&5&public:&
&6&&&&&CA();&
&9&CA::CA():max(<span style="color: #0)&
<span style="color: #&{&
<span style="color: #&}&
4、Reference&引用型变量:
&&&&& 引用型变量和const变量类似。需要在创建的时候即进行初始化。也是在初始化列表中进行。但需要注意用Reference类型。&&
&1&class&CA&
&3&public:&
&4&&&&&int&&
&5&&&&&int&&&
&6&public:&
&7&&&&&CA();&
<span style="color: #&CA::CA():&counter(&init)&
<span style="color: #&{&
<span style="color: #&}&
5、const static integral&变量:
&&&& 对于既是const又是static&而且还是整形变量,C++是给予特权的(但是不同的编译器可能有会有不同的支持,VC 6好像就不支持)。可以直接在类的定义中初始化。short可以,但float的不可以哦。
&1&//&例float类型只能在类外进行初始化&
&2&//&const&float&CA::fmin&=&3.14;&
&3&class&CA&
&5&public:&
&6&&&&& //static&const&float&fmin&=&0.0;//&only&static&const&integral&data&members&can&be&initialized&within&a&class&
&7&&&& const&static&int&nmin&=&<span style="color: #;&
&8&&&& &#8230;&#8230;&
&9&public:&
<span style="color: #&&& &#8230;&#8230;&&&
<span style="color: #&};&
总结起来,可以初始化的情况有如下四个地方:
1、在类的定义中进行的,只有const&且&static&且&integral&的变量。
2、在类的构造函数初始化列表中,&包括const对象和Reference对象。
3、在类的定义之外初始化的,包括static变量。因为它是属于类的唯一变量。
4、普通的变量可以在构造函数的内部,通过赋值方式进行。当然这样效率不高。
阅读(...) 评论() &C++成员变量、构造函数的初始化顺序 - DoubleLi - 博客园
一、C++成员变量初始化
1、普通的变量:一般不考虑啥效率的情况下&可以在构造函数中进行赋值。考虑一下效率的可以再构造函数的初始化列表中进行
2、static&静态变量(本地化数据和代码范围):
static变量属于类所有,而不属于类的对象,因此不管类被实例化了多少个对象,该变量都只有一个。在这种性质上理解,有点类似于全局变量的唯一性。
函数体内static变量的作用范围时该函数体,不同于auto变量,该变量内存只被分配一次,因此其值在下次调用时维持上次的值。
在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外的其它函数访问。
在模块内的static函数只可被这一模块内的其他函数调用,这个函数的适用范围被限制在声明它的模块内。
在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝。
在类中的static成员函数属于整个类所拥有,这个函数不接受this指针,因而只能访问类的static成员变量。
3、const&常量变量:
const常量需要在声明的时候即初始化。因此需要在变量创建的时候进行初始化。一般采用在构造函数的初始化列表中进行。
4、Reference&引用型变量:
引用型变量和const变量类似。需要在创建的时候即进行初始化。也是在初始化列表中进行。但需要注意用Reference类型。
4、字符串初始化
char str[10] = "HELLO";
结尾会被编译器自动加上结尾符'/0',编译的时候可以看到它最后是'',ASC码值是0;
"HELLO"只有5个字符,加上编译器自动添加的'/0',也就是会初始化数组的前6个元素,剩下有元素会被全部初始化为'/0',这个要注意哦
char str[] = "HELLO";
编译器自动为后面的字符串分配大小并加'/0'
char str[] = {'H','E','L','L','O','/0'};
编译器会根据字符串大小分配空间,可是不会自动分配'/0',所以结尾的时候要自己加上'/0'
char *str = "HELLO";
把指向字符串的指针给定义好的字符指针
1)用构造函数确保初始化
对于一个空类,编译器会自动声明4个默认函数:构造函数、拷贝构造函数、赋值函数、析构函数(如果不想使用自动生成,就应该明确拒绝),这些生成的函数都是public且inline的。
2)为什么构造函数不能有返回值
3)为什么构造函数不能为虚函数
虚函数调用的机制,是知道接口而不知道其准确对象类型的函数,但是创建一个对象,必须知道对象的准确类型;当一个构造函数被调用时,它做的首要事情之一就是初始化它的VPTR来指向VTABLE。
面试题:构造函数
#include &iostream&
class Base {private: public: Base(int x) {
class Derived : public Base{private: public: Derived(int x, int y) {
i = } void print() {
cout && i + Base::i && }};
int main(){ Derived A(2,3); A.print();
return 0;}
首先,是访问权限问题,子类中直接访问Base::i是不允许的,应该将父类的改为protected或者public(最好用protected)
其次,统计父类和子类i的和,但是通过子类构造函数没有对父类变量进行初始化;此处编译会找不到构造函数,因为子类调用构造函数会先找父类构造函数,但是没有2个参数的,所以可以在初始化列表中调用父类构造函数
最后个问题,是单参数的构造函数,可能存在隐式转换的问题,因为单参数构造函数,和拷贝构造函数形式类似,调用时很可能会发生隐式转换,应加上explicit关键字
#include &iostream&
class Base {protected: public: explicit Base(int x) {
class Derived : public Base{private: public: Derived(int x, int y):Base(x) {
i = } void print() {
cout && i + Base::i && }};
int main(){ Derived A(2,3); A.print();
return 0;}
2、初始化列表
1)使用初始化列表提高效率
class Student {public: Student(string in_name, int in_age) {
name = in_
age = in_ }private :
因为在构造函数中,是对name进行赋值,不是初始化,而string对象会先调用它的默认构造函数,再调用string类(貌似是basic_string类)的赋值构造函数;对于上例的age,因为int是内置类型,应该是赋值的时候获得了初值。
要对成员进行初始化,而不是赋值,可以采用初始化列表(member initialization list)
class Student {public: Student(string in_name, int in_age):name(in_name),age(in_age) {}private :
在初始化的时候调用的是string的拷贝构造函数,而上例会调用两次构造函数,从性能上会有不小提升
有的情况下,是必须使用初始化列表进行初始化的:const对象、引用对象
2)初始化列表初始顺序
#include &iostream&
class Base {public: Base(int i) : m_j(i), m_i(m_j) {} Base() : m_j(0), m_i(m_j) {} int get_i() const {
return m_i; } int get_j() const {
return m_j; }
private: int m_i; int m_j;
int main(){ Base obj(98); cout && obj.get_i() && endl && obj.get_j() &&
return 0;}
输出为一个随机数和98,为什么呢?因为对于初始化列表而言,对成员变量的初始化,是严格按照声明次序,而不是在初始化列表中的顺序进行初始化,如果改为赋值初始化则不会出现这个问题,当然,为了使用初始化列表,还是严格注意声明顺序吧,比如先声明数组大小,再声明数组这样。
C++构造函数初始化按下列顺序被调用:
首先,任何虚拟基类的构造函数按照它们被继承的顺序构造;
其次,任何非虚拟基类的构造函数按照它们被继承的顺序构造;
最后,任何成员对象的构造函数按照它们声明的顺序调用;
#include &iostream&class OBJ1{
OBJ1(){ cout&&"OBJ1\n"; }};class OBJ2{
OBJ2(){ cout&&"OBJ2\n";}}class Base1{
Base1(){ cout&&"Base1\n";}}class Base2{
Base2(){ cout &&"Base2\n"; }};class Base3{
Base3(){ cout &&"Base3\n"; }};class Base4{
Base4(){ cout &&"Base4\n"; }};class Derived :public Base1, virtual public Base2,public Base3, virtual public Base4//继承顺序{
Derived() :Base4(), Base3(), Base2(),Base1(), obj2(), obj1(){//初始化列表
cout &&"Derived ok.\n";
protected:
OBJ1 obj1;//声明顺序
OBJ2 obj2;};
int main(){
cout &&"This is ok.\n";
return 0;}结果:Base2 //虚拟基类按照被继承顺序初始化Base4 //虚拟基类按照被继承的顺序 Base1 //非虚拟基类按照被继承的顺序初始化Base3 //非虚拟基类按照被继承的顺序 OBJ1
//成员函数按照声明的顺序初始化OBJ2
//成员函数按照声明的顺序 Derived ok. This is ok.C++学习总结和归纳
面向对象技术基础1.构造函数和析构函数和特殊成员构造函数的作用:PS:构造函数可以在类外定义1.给对象一个标识符2.为对象数据成员开辟内存空间3.完成对象数据成员的初始化4.如果没有显示定义构造函数,则默认构造函数只完成1、2两步5.初始化表达式:1.可用于初始化类的任意数据成员,static数据成员除外(在类外初始化)2.只能用初始化表初始化基类,const数据成员,引用成员,类对象成员3.Const数据成员,只能在初始化表中初始化,必须显示的定义构造函数,而且要注意类中const整型数据成员不能作为常量指明一个数组的大小(运行才确定)复制构造函数:1.原型:Point::Point(constPoint&pt);2.调用:Pointpt2=pt1;或者Pointpt2(pt1);3.默认复制构造函数:将源对象中的成员按“内存单元复制”的方式复制到目的对象中,复制后,源对象和目的对象除了地址不同外,各个成员的取值都是相同的,特别是对于含有指针类型的数据成员,指向的内存单元相同4.显示定义复制构造函数:1.类中含有指针型的数据成员,需要使用动态内存的,需要显示定义2.自定义复制构造函数,也可以使用初始化表来给目的对象赋值构造函数注意点:1.如果类中有类对象成员,那么该对象所在的类中必须定义了无参构造函数或所有参数都有默认值的构造函数,或默认构造函数,否则不合法(对象成员所占内存空间无法开辟,编译器报错)2.只要自定义了构造函数(包括复制构造函数),则编译器不会提供默认构造函数Static数据成员和static成员函数1.static数据成员在编译的时候就被创建,此时仅知道如何分配内存,但是必须在类外(cpp文件中)进行初始化2.类定义:Classcompute{pivate:staticfloattotal_p}3.在cpp文件中初始化(不能再使用static关键字):floatcompute::total_pice=0;4.静态成员函数只能调用静态成员变量,但是可以在函数中创建一个本类对象(当构造函数定义为pivate类型后),也可以delete一个本类对象(析构为pivate型)5.如果静态数据成员使用const修饰,而且是整型,浮点类型、布尔类型或枚举型,但不能是类对象,数组、引用和指针,C++允许该成员在类定义中初始化,此时不能再外部再次对该静态成员进行定义性声明,但可以对该成员进行引用性声明6.定义性声明:指在一个文件中定义一个全局变量,如inta;7.引用性声明:指当该文件需要使用另一个文件的某个变量时,则需要使用引用性声明这个是另一个文件中的全局变量:extenalinta;Const对象和Const成员函数1.const成员函数无法修改数据成员,否则编译器报错2.定义:voidpint()const{函数体内不能修改数据成员}3.能作用于const对象的成员函数除了构造函数和析构函数外,就只有const成员函数了,因为const对象只能被创建,撤销以及只读访问。即:const对象只能调用const成员函数(对应只读访问)对象的大小:1.对象在内存中以结构的形式(只包括非static数据成员),存放在数据段中或堆中2.Sizeof(),计算的是所有非static成员的大小,注意还要保证数据对齐(填充),引用成员当指针来维护,类中有虚函数还需要额外分配一个指针指向虚函数表(+4)3.Static成员变量在编译期就已经在静态存储区分配了内存,在程序整个运行期间4.类中的成员函数存在于代码段中,一个类只有一个副本this指针:1.this指针隐含在成员函数内的一种指针,指向本对象的指针2.this指针和对象同生共死,具有类作用域3.主要作用:a.显示指明类中数据成员;.返回本对象的指针或引用(etun*this)4.Const类名*constthis:表示在程序中即无法修改this指针(constthis),也无法通过指针this指针修改该对象(Const类名)构造函数允许按参数默认方式调用(带有多个默认值得构造函数)classA{pivate:intx;inty;pulic:A(intxyp=0){x=y=cout"一个默认值的构造函数被执行"}如果没有默认值的情况下,则Aa(1);编译A(intxp=0,intyp=0){能通过,调用的是第一个构造函数x=y=cout"两个默认值的构造函数被执行"}};intmain(){Aa1(1);编译出错,不知道选择哪个构造函数Aa2(1,2);编译通过,调用的是第二个构造函数etun0;}Point构造函数:合法创建对象:Point(intx=0,inty=0){Pointxpos=x;ypos=y;Pointpt(3);}Pointpt(3,4);使用new和delete为对象数组分配释放动态空间:1.Point*p=newpoint[2];申请了一块内存,连续存放连个point对象,此时不能显示调用对象的构造函数,因此,对象要么没有定义任何形式的构造函数(编译器提供),要么显示定义了一个(有且只能有一个:否则无法判断调用哪个构造函数)所有参数都有默认值的构造函数(包括无参构造函数)。PS:只能使用p[0]来访问对象,如果使用p-pint();p++;来访问则delete[]p;p=NULL;操作会出错2.delete[]p;释放了数组所占的内存空间,new和delete激活了数组中每个对象的构造函数和析构函数3.malloc和fee不能为对象动态的申请内存,因为无法像newdelete或newdeltete[]那样自动调用对象的构造函数和析构函数4.deletep;操作后p指针不会被销毁,而且指向原来的地方,应及时的置NULL内存空间结构
& 果果文库所有资源均来源于互联网,仅供网友学习交流,若侵犯了您的权益,请联系我们予以删除。
14540&&人浏览
7957&&人浏览
12793&&人浏览
6032&&人浏览
12932&&人浏览
18922&&人浏览
7464&&人浏览
4102&&人浏览
15626&&人浏览
6708&&人浏览
13882&&人浏览
9758&&人浏览
10054&&人浏览
17916&&人浏览
18722&&人浏览
本文标题:C++学习总结和归纳 链接地址:
2013- Inc. All Rights Reserved 果果文库 版权所有 联系站长: ; 经营许可证编号:浙ICP备号在 SegmentFault,解决技术问题
每个月,我们帮助 1000 万的开发者解决各种各样的技术问题。并助力他们在技术能力、职业生涯、影响力上获得提升。
一线的工程师、著名开源项目的作者们,都在这里:
获取验证码
已有账号?
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
int _a = 2; //直接赋值
什么情况下应该这样赋值,什么情况下应该在构造函数里赋值?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
int _a = 2; // 类内初始化
这样的写法与
A() : _a(2) {}
// 构造函数初始化列表
效果相同,赋初值的过程都会发生在构造函数的成员初始化阶段,前者只是 C++11 增加的语法糖。这样如果类有多个构造函数的时候,如果一个成员的初值在这些构造函数中相同,那么就可以通过类内初始化的方式设置初值,减少重复劳动。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
就地初始化(“直接赋值”)比较好,简洁明了
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
我猜你应该是想在每一个类初始化的时候就把_a赋值为2吧?这种情况就把int _a = 2写到A的默认构造函数里面好了。
A(){_a = 2;}
还是说你想多个类的实例共享一个_a变量?这种情况你应该用static关键字
static int _a;
还要注意一下访问权限
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
就地初始化
这个比较方便的是可以直接在声明的时候使用type var=?或者type var{}赋值,可以摆脱一个为了初始化而写构造函数的麻烦,不过这需要最新的c++11标准才行,相对于初始化列表,不用再为了摆脱编译器的初始化与声明顺序不一致的警告(这有时候其实是非常危险的)调整变量在初始化列表中的顺序。
struct Init
int x = 11;
int z {10};
初始化列表
初始化列表是一种非常“古老”的初始化方式,相对于就地初始化优势也很明显,并不需要什么新特性支持,c++所有版本都能支持,还有一个好处就是可以用来委托构造(c++11)。
struct InitList
InitList()
:InitList(10, 11)
InitList(int x, int z)
至于用什么是属于个人习惯的问题,初始化列表更通用一些,当前也可以结合两者一起使用。
注意:当一个成员在初始化列表和就地初始化同时存在时,初始化列表优先执行,就地初始化会被忽略。
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
类内初始值会被转写进构造函数里所以并没有任何区别由于写了类内初始值的成员的初始化顺序依然会按默认顺序,所以我推荐不写类内初始值
同步到新浪微博
分享到微博?
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:为什么说“如果类的定义至少包含一个构造函数,就不能使用初始化列表创建类的对象,而必须用构造函数来创建。”?
例如:
将Program 12.2中的Box firstBox(80.0, 50.0, 40.0);换为Program 12.1中的
Box firstBox = {
为什么说“如果类的定义至少包含一个构造函数,就不能使用初始化列表创建类的对象,而必须用构造函数来创建。”?
例如:
将Program 12.2中的Box firstBox(80.0, 50.0, 40.0);换为Program 12.1中的
Box firstBox = { 80.0, 50.0, 40.0 };之后程序就不能正常运行了,
请问这是为什么?
Program 12.1 在此!!!!!!!!!!!!!!!
// Program 12.1
using std::
using std::
// Class to represent a box
class Box {
// Function to calculate the volume of a box
double volume() {
return length * width *
int main() {
Box firstBox = { 80.0, 50.0, 40.0 };
// Calculate the volume of the box
double firstBoxVolume = firstBox.volume();
cout << "Size of first Box object is "
<< firstBox.length
<< firstBox.width << " by "
<< firstBox.height
cout << "Volume of first Box object is " << firstBoxVolume
Box secondBox = firstB
// Create a second Box object the same as firstBox
// Increase the dimensions of second Box object by 10%
secondBox.length *= 1.1;
secondBox.width *= 1.1;
secondBox.height *= 1.1;
cout << "Size of second Box object is "
<< secondBox.length << " by "
<< secondBox.width << " by "
<< secondBox.height
cout << "Volume of second Box object is " << secondBox.volume()
cout << "Increasing the box dimensions by 10% has increased the volume by "
<< static_cast
((secondBox.volume()-firstBoxVolume)*100.0/firstBoxVolume)
std:: t();
return 0;
}
Program 12.2 在此!!!!!!!!!!!!!!!
// Program 12.2
using std::
using std::
// Class to represent a box
class Box {
// Constructor
Box(double lengthValue, double widthValue, double heightValue) {
cout << "Box constructor called" <<
length = lengthV
width = widthV
height = heightV
// Function to calculate the volume of a box
double volume() {
return length * width *
int main() {
Box firstBox(80.0, 50.0, 40.0);
// Calculate the volume of the box
double firstBoxVolume = firstBox.volume();
cout << "Size of first Box object is "
<< firstBox.length
<< firstBox.width << " by "
<< firstBox.height
cout << "Volume of first Box object is " << firstBoxVolume
std:: t();
return 0;
}
如果你的类没有显式定义任何构造函数,那么C++编译器会自动为你生成一个没有任何参数的构造器,成为默认构造器;如果有一个或以上的用户定义的构造器,c++编译器就不再自动生成构造器了。因此任何一份额C++类至少有一个构造器。
类对象在创建时,如果没有显式采用构造器,C++编译器就会自动调用默认构造器进行类的创建工作,如果你自己定义了构造器,系统就没有了默认构造器,因此,你就必须显式调用构造器。
12.2中定义了Box(double lengthValue, double widthValue, double heightValue)构造器,因此Box firstBox = { 80.0, 50.0, 40.0 }; 能够正常运行;12.1中没显式定义,那么系统为你生成一个默认构造器,那么Box firstBox = { 80.0, 50.0, 40.0 }; 就会找不到构造器而编译失败!
这是C++的编译的一般...
构造函数是一个特殊的成员函数,能够自动初始化对象。(不论何时创建对象,该特殊的成员函数,即构造函数都将被执行)
构造函数用于创建对象并使用传递到其中的参数初始化...
public Class1()
super(5);//可以是其他数,这句就是调用了
//public BaseClass(int x)
近下载了软件安装的时候,经常看到这个NSIS error的提示。
The installer you are trying to use is corrupte...
在方法定义时加上virtual,表示此方法是虚拟方法,可供子类覆盖,修改父类的执行
#include//包含输入输出流头文件
#include//包含字符串处理头文件,
//本例中使用了strcpy()函数
class Pen//定义类名称
答: bpd+hc+ac fl男女可以看出来吗?是通过哪些数值看出来的啊?
答: 如果你理解能力强考数据库,其中比如关系数据库之类的需要去领悟
如果你记忆能力强考网络,各种各样的名词,背下来就得分。
还有官方指定的教材要有,上机最好做一做南开...
答: 新年好!首先,你必须了解计算机的组成和结构以及操作系统的运作原理,这是基础
如果你想学习开发多线程、WINDOWS应用、动态链接库、WINDOWS组件的话,建议...
大家还关注
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区
相关问答:123456789101112131415}

我要回帖

更多关于 java 成员变量初始化 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信