小知识点
-
成员函数参数的默认值要写在类中
类外就不要再写默认值了 -
c++鼓励数据和操作封装在一起
-
对象之间的相互通信是通过( 调用成员函数 )实现的。
-
在类中,如果不作特别说明,所有的数据均为私有类型
-
三种访问限定符出现的次数为(任意多次)
-
构造函数先构造再执行体内函数
析构函数先执行体内函数再析构(析构顺序是变量创建的逆序,即类似于栈) -
构造函数不能定义返回值类型,也不能包括return语句
可以是内联函数,可以有形参也可以没有
可以重载 -
自身类对象不能作为类的成员
默认构造函数
调用时可以不需要实参:
参数列表都为空或全部参数都有默认值
Clock();
Clock(int x=2,int y=1);
这两个是一样的都是默认构造函数
委托构造函数
使用类的其他构造函数进行初始化的过程
eg.
Clock::Clock(int x,int y):x(x),y(y){}
Clock::Clock():Clock(0,0){}
下面的就直接用了上面的构造函数
析构函数
完成对象被删除前的一些操作,因此是先执行函数体,然后才析构
在对象的生存期结束后自动调用
一个类中只能定义一个析构函数
~Point();
default和delete
Clock()=default;
指示编译器生成默认构造函数
Clock()=delete;
结构体
缺省参数为public
联合体
成员共用相同的内存单元
任何两个成员不会同时有效
枚举
不限定作用域的枚举类型:
enum 枚举类型名 {变量值列表}
enum week{Sun,Mon,Tue};
枚举元素按照常量处理,不能Sun=1
这样赋值
默认值从0开始
枚举型数据可以隐含转化为整形数据,但是整形数据不能直接赋值给枚举变量,需要强制类型转化
强类型枚举:
enum class 枚举类型名:底层类型{枚举值列表};
实验一
#include<iostream>
using namespace std;
class Clock{
private:
int a;
public:
Clock()=delete;
Clock(int x=2){a=x;}
//这个函数,如果写Clock m;就错了(因为Clock()=delete;)
//这个必须给int x 传入参数
void print(){
cout<<a<<endl;
}
};
/*
这里主要是验证一下delete的用法
如果在类中写了Clock()=delete;
那么后面就不能写Clock m;因为这种无参数的默认构造函数已经被删除了
*/
int main(){
Clock m;
//Clock m();//不能这么创建一个对象,只有在只有在传参的时候才这么写
m.print();
return 0;
}
类的组合实验
私以为不仅在调用函数时候需要调用复制构造函数,在初始化列表中也需要调用复制构造函数
/*
一个简单的组合类的程序
用于复习
*/
#include<iostream>
#include<math.h>
using namespace std;
//Point类
class Point{
public:
Point(int xx=0,int yy=0);
Point(Point &P);
int getX(){return x;}
int getY(){return y;}
private:
int x,y;
};
Point::Point(int xx,int yy){
cout<<"Point构造函数"<<endl;
x=xx;y=yy;
}
Point::Point(Point &P){
x=P.x;y=P.y;
cout<<"Point复制构造函数"<<endl;
}
//Line类
class Line{
public:
Line(Point p1,Point p2);
Line(Line &L);
double getlen(){return len;}
private:
Point p1,p2;
double len;
};
Line::Line(Point p1,Point p2):p1(p1),p2(p2){
double x=static_cast<double>(p1.getX()-p2.getX());
double y=static_cast<double>(p1.getY()-p2.getY());
len=sqrt(x*x+y*y);
cout<<"Line构造函数"<<endl;
}
Line::Line(Line &L):p1(L.p1),p2(L.p2){
cout<<"Line复制构造函数"<<endl;
double x=static_cast<double>(p1.getX()-p2.getX());
double y=static_cast<double>(p1.getY()-p2.getY());
len=sqrt(x*x+y*y);
}
int main(){
Point myp1(1,1),myp2(4,5);
Line line(myp1,myp2);
cout<<endl;
Line line2(line);
cout<<line.getlen()<<endl;
cout<<line2.getlen()<<endl;
return 0;
}
改变枚举值的默认值实验
#include<iostream>
using namespace std;
enum x{a=7,b,c,d};
int main(){
x x1=a;
x x2=b;
x x3=c;
cout<<x1<<endl<<x2<<endl<<x3<<endl;
return 0;
}
题目一
输出为?
#include<iostream>
using namespace std;
class ONE{
int c;
public:
ONE(): c(0){cout<<1;}
ONE(int n): c (n){cout<<2;}
};
class TWO{
ONE onel;
ONE one2;
public:
TWO(int m): one2(m){cout<<3;}
};
int main(){
TWO t(4);
return 0;
}
注意这个程序
TWO t(4)会先调用内嵌对象的构造函数,并不是说调用这个构造函数的one2(m)
然后就先构造一个one2类型的了
而是根据变量的定义顺序,先后定义ONE onel; ONE one2;
因此会先调用ONE(): c(0){cout<<1;}
然后调用ONE(int n): c (n){cout<<2;}
最终输出123
题目二:析构函数的执行顺序以及构造成员时候的顺序
#include <iostream>
using namespace std;
class B1 {
int b1;
public:
B1(int i=0) { b1=i; }
~B1() { cout<<b1; }
};
class B2 {
int b2;
public:
B2(int i) { b2=i; }
~B2() { cout<<b2; }
};
class B3 {
int b3;
public:
B3(int i) { b3=i; }
~B3() { cout<<b3; }
};
class D{
int d;
B2 b2;
B3 b3;
B1 b1;
public:
D(int i,int j,int k):b2(i),b3(j) { d=k; }
~D() { cout<<d; }
};
int main(){
D d(4,2,1);
return 0;
}
输出1024