c++类的学习笔记;
类中所有对象都有自己的存储空间,但是,方法由所有对象共享,即方法只有一个副本
例如:有一个类 class Stock{};
Stock acce,bcce;
类有一个方法叫void show(int ,double,...){//...}
类中定义了成员变量 int a;double c;
acce.show() ,与 bcce.show()占据同一块内存。
acce.a 与 bcce.a 占据不同的内存。
类在实现构造函数的同时,也会存在一个析构函数{Stock && ~Stock}
构造函数默认为无参数的 Stock();并可以省略。
但是,当存在多个构造函数时,默认构造函数,即不含参数的构造函数不可省略。否则编译器会警告。
建议采用初始化的方式设置对象的值,而不是采用赋值的方式:
Stock stock1 = Stock(x,y,z,...);//初始化
Stock stock2;stock2 = Stock(x,y,z,...);//赋值
当然如果是C++11,可以采用大括号赋值 即 Stock stock1 {x,y,z,...}; Stock stock2 = {x,y,z,...};
注意有一种设置方式:Stock stock3 = 55;//设置value。这是尽量要避免的
this 指针可以指代当前操作对象,而不必特地传入一个指针来指向本身(作用于调用自身成员函数时使用)
比如copy时
Stock& Stock::copy_a(const Stock& rhs)
{
if(this != &rhs)//如果要赋值的对象与自己不相等,则
{
x = rhs.x;
y = rhs.y;
//...
}
return *this;//返回本身的副本
}
注:每个成员函数都拥有一个this指针,指向调用对象。
C++11 中设置了一种新的枚举方式来解决枚举名冲突的问题
enum class egg{Small,Large,Jumbo};//可以使用struct替换class
enum class Tshirt{Small.Large,Jumbo};
这样就形成一种作用域类型的枚举,防止常量冲突。 使用时附带作用域名:
egg::Small; Tshirt::Small;
但是却不能隐式的转换为整形,需要时需要显式转换 int(egg::Small);
非作用域的枚举则可以隐式转换。
在类设计时,对于函数返回的一个要点:
在函数里创建临时变量,无论是简单类型还是,自己的类对象,都是属于临时变量,那么在返回的时候
便不能返回它的引用或者他的指针,否则在返回后,该变量会被删除。导致返回值引用或者指向一个无效
的变量,而返回它本身则会让程序在删除它之前创建一个它的拷贝,返回给调用,这样才能达到我们的预期。
重载运算符:
关键字是:operator
使用方法:返回值 作用域::operator运算符(参数){ /*重载之后的功能*/ }
运算符必须是C++里内置的而不能是自己定义的。
重载运算符的操作数至少有一个是用户自己定义的类型,这是为了防止将内置的标准类型重置运算符。如将(1 + 1)变成(1 - 1)的功能;
重载运算符时候会遇到一个问题,即选择成员函数,还是非成员函数
具体来说,还是举个例子。
这个相比之下,非成员函数和成员函数的差别就在于,参数的传递,非成员函数使用比成员函数多一个参数,原因在于,成员函数使用this指针
隐形传递参数。
当重载运算符所作的运算过多时,那么可以考虑使用构造函数来帮助你实现你的目的,相当于新建一个新的对象并且赋值给调用对象。
例如,举个栗子:
我们有一个类Rectangle 其中包含有属性,长,宽,面积,(x,y,area).
area 通过成员函数 set_area() 来设置,那么如果我们要让两个长方形的长和宽相加,并得到新的长方形的面积,我们如果用常规的方法,循规蹈矩的
十分麻烦,而我们可以通过设置构造函数Rectangle(double n1,double n2){x = n1;y = n2;set_area();}来一步实现
即 Rectangle operator+(const Rectangle &R){return Rectangle(x+R.x,y+R.y);}
类中所有对象都有自己的存储空间,但是,方法由所有对象共享,即方法只有一个副本
例如:有一个类 class Stock{};
Stock acce,bcce;
类有一个方法叫void show(int ,double,...){//...}
类中定义了成员变量 int a;double c;
acce.show() ,与 bcce.show()占据同一块内存。
acce.a 与 bcce.a 占据不同的内存。
类在实现构造函数的同时,也会存在一个析构函数{Stock && ~Stock}
构造函数默认为无参数的 Stock();并可以省略。
但是,当存在多个构造函数时,默认构造函数,即不含参数的构造函数不可省略。否则编译器会警告。
建议采用初始化的方式设置对象的值,而不是采用赋值的方式:
Stock stock1 = Stock(x,y,z,...);//初始化
Stock stock2;stock2 = Stock(x,y,z,...);//赋值
当然如果是C++11,可以采用大括号赋值 即 Stock stock1 {x,y,z,...}; Stock stock2 = {x,y,z,...};
注意有一种设置方式:Stock stock3 = 55;//设置value。这是尽量要避免的
this 指针可以指代当前操作对象,而不必特地传入一个指针来指向本身(作用于调用自身成员函数时使用)
比如copy时
Stock& Stock::copy_a(const Stock& rhs)
{
if(this != &rhs)//如果要赋值的对象与自己不相等,则
{
x = rhs.x;
y = rhs.y;
//...
}
return *this;//返回本身的副本
}
注:每个成员函数都拥有一个this指针,指向调用对象。
C++11 中设置了一种新的枚举方式来解决枚举名冲突的问题
enum class egg{Small,Large,Jumbo};//可以使用struct替换class
enum class Tshirt{Small.Large,Jumbo};
这样就形成一种作用域类型的枚举,防止常量冲突。 使用时附带作用域名:
egg::Small; Tshirt::Small;
但是却不能隐式的转换为整形,需要时需要显式转换 int(egg::Small);
非作用域的枚举则可以隐式转换。
在类设计时,对于函数返回的一个要点:
在函数里创建临时变量,无论是简单类型还是,自己的类对象,都是属于临时变量,那么在返回的时候
便不能返回它的引用或者他的指针,否则在返回后,该变量会被删除。导致返回值引用或者指向一个无效
的变量,而返回它本身则会让程序在删除它之前创建一个它的拷贝,返回给调用,这样才能达到我们的预期。
重载运算符:
关键字是:operator
使用方法:返回值 作用域::operator运算符(参数){ /*重载之后的功能*/ }
运算符必须是C++里内置的而不能是自己定义的。
重载运算符的操作数至少有一个是用户自己定义的类型,这是为了防止将内置的标准类型重置运算符。如将(1 + 1)变成(1 - 1)的功能;
同样,也支持两个对象以上的重载操作,例如 重载“+” 用于Stock类的运算
Stock operator+(const Stock &t){Stock temp;temp.x = x + t.x;return temp;}
上述式子转换为:
<pre name="code" class="cpp">Stock t1 = t2.operator+(t3.operator+(t4));
得到我们预期的目的。 友元函数与运算符重载的运用。 我们看到,C++内置的标准类型通过 重载 << 运算符 可以由std::cout 任意输出,十分方便,我们自己定义的类型呢?当然可以: 首先,为了不破环iostream文件内容,采用在自己的类中使用友元函数来实现这个功能: 声明时,在类中声明,带上friend关键字在最前方。 定义时,不带friend关键字。
friend std::ostream operator<<(std::ostream &os,const Stock &t);//声明
std::ostream & operator<<(std::ostream &os,const Stock &t){
os << t.x << t.y ....;return os;
}//定义,伪代码。
记得定义时不带作用域运算符。
重载运算符时候会遇到一个问题,即选择成员函数,还是非成员函数
具体来说,还是举个例子。
重载一个“*”运算符,使之能作用于类Stock。
Stock operator+(const Stock &t){Stock temp;temp.x = x + t.x;return temp;}
Stock st1,st2;
st1 += st2;//成功,这就是所谓的成员函数现象 ==>st1 = st1.operator+(st2);
st1 = 2*st2;//这就完蛋了,因为2,不是Stock类,不能调用这个operator+函数啊!怎么办?这就是非成员函数的作用,友元来了
//friend Stock operator*(const Stock &s1,const Stock &s2 ){Stock temp;temp.x = s1.x + s2.x;return temp;} 这就可以啦。
//用这句话替换上面那句话,这就可以啦。
这个相比之下,非成员函数和成员函数的差别就在于,参数的传递,非成员函数使用比成员函数多一个参数,原因在于,成员函数使用this指针
隐形传递参数。
当重载运算符所作的运算过多时,那么可以考虑使用构造函数来帮助你实现你的目的,相当于新建一个新的对象并且赋值给调用对象。
例如,举个栗子:
我们有一个类Rectangle 其中包含有属性,长,宽,面积,(x,y,area).
area 通过成员函数 set_area() 来设置,那么如果我们要让两个长方形的长和宽相加,并得到新的长方形的面积,我们如果用常规的方法,循规蹈矩的
十分麻烦,而我们可以通过设置构造函数Rectangle(double n1,double n2){x = n1;y = n2;set_area();}来一步实现
即 Rectangle operator+(const Rectangle &R){return Rectangle(x+R.x,y+R.y);}