C++期末复习随便写写加深一下印象
C++基础复习—— 类与对象
类和对象
类=数据+操作(函数)
1.类
(1)语法: class 类名{ public: 函数主要在类外使用,可以在类外访问 protected: private: 如果只为类内中的其他函数使用一般设为private }; (2)使用域限定符 “::”
2.构造函数
(1)缺省构造函数:没有构造函数时,系统会自动生成一个默认构造函数,默认所有数据成员值均为其所在数据类型为、意义中的0。 (2)拷贝构造函数:用已经存在的类的对象去构造一个新的对象,两个对象的数据成 员值是完全相同的。 声明格式:
Point(Point&);
Point(const Point&);
拷贝函数被调用的三种情况:
-
用已经存在的对象初始化另一个对象
-
对象作为实参传递给形参时
-
对象作为函数返回值时
例:
class Point
{
public:
Point(int xx = 0, int yy = 0) { X = xx; Y = yy; }
Point(Point &p); //拷贝构造函数
int GetX() { return X; }
int GetY() { return Y; }
void SetX(int x) { X = x; }
void SetY(int y) { Y = y; }
private:
int X;
int Y;
};
Point::Point(Point &p)
{
X = p.X;
Y = p.Y;
cout << "Copy constructor is called." << endl;
}
Point Fun(Point p)
{
Point p1;
p1.SetX(p.GetX() + 2);
p1.SetY(p.GetY() + 2);
return p1;
}
int main()
{
Point A(1, 2);
Point B(A); //拷贝构造函数被调用,给B赋值
Point C;
C = Fun(A);
cout << B.GetX() << "," << B.GetY() << endl;
cout << C.GetX() << "," << C.GetY() << endl;
return 0;
}
调试结果如下: 1,2 3,4
3.析构函数
析构函数是用来完成对象被删除之前的一些清理工作的;析构函数是在对象的生存期即将结束的时刻由系统自动调用。调用完成,对象消失,其内存空间被释放。 声明格式:(以Person类为例) ~Person();
注意:
- 析构函数不允许有参数,所以一个类中只能有唯一的析构函数。
- 先构造的后析构,后构造的先析构(栈)
- 构造函数与析构函数的调用顺序例题:
class Person
{
public:
Person(char* input_name)
{
name = new char[20];
strcpy(name, input_name);
cout << name << " Constructor Called." << endl;
}
~Person()
{
cout << name << " Destructor Called." << endl;
delete[] name;
}
void show();
private:
char *name;
};
void Person::show()
{
cout << name << endl;
}
int main()
{
Person student1("zhangming");
Person student2("lixin");
student1.show();
student2.show();
return 0;
}
调试结果如下: zhangming Constructor Called. lixin Constructor Called. zhangming lixin lixin Destructor Called. zhangming Destructor Called.
4.常成员
(1)const修饰符 定义常对象语法:
const class_Type object_name;
or
class_Type const object_name;
定义常引用语法:const data_Type & reference_name 常引用经常被用做参数的形参,它能提高函数的运行效率,节省内存,并保证实参不会被更改。 以下为原代码示例:
void display(const int& d);
int main()
{
int d(2008);
display(d);
return 0;
}
void display(const int& d)
{
cout<<d<<endl;
}
然而这是一个错误程序,我们来看看报错吧: [Error] assignment of read-only reference ’d’ d不可被修改! (2)常数据成员
- 使用const说明的数据成员我们称为常数据成员。
- 如果一个类中存在常数据成员,那么任何函数成员都不能对该成员赋值。
- 常数据成员只能在构造函数的初始化列表位置进行初始化
例题:
class Point
{
public:
Point(double new_x,double new_y);
Point(const Point& p);
void disp();
private:
double x;
const double y; //常数据成员y
};
Point::Point(double new_x,double new_y):y(new_y)
//初始化列表初始化常数据成员y
{
x=new_x;
}
Point::Point(const Point& p):y(p.y)
//初始化列表初始化常数据成员y
{
x=p.x;
}
void Point::disp()
{
cout<<"该点的坐标为:("<<x<<","<<y<<")"<<endl;
}
int main()
{
Point p1(1,2),p2(p1);
p1.disp();
p2.disp();
return 0;
}
(3)常函数成员
说明格式:
return_type function_name(formal parameters list)const; 由于有了const的修饰,该常函数成员和一般函数成员就有了不同,它不能更新对象的数据成员,也不能调用非常函数成员,这样就保证了常函数成员不会改变数据类型成员的值。(const关键字可以被用于对重载函数的区分,例如:void disp(); void disp()const;)
- 常函数成员做只读操作
- 常对象只调用常函数
- 常函数可以给常/非常对象使用
(4)常对象 对象被const修饰(例如:const Point p(4,5);),因此变成一个常对象,和一般常变量一样,常对象在进行定义时必须进行初始化,而且在生存期内不能被改变。常对象只能调用常函数成员是专门给常对象而准备的。
5.指向对象的指针
(1)对象指针 语法:
Person *p_Person;
Person p1;
p_Person=&p1;
等价于 Person p1,*p_Person=&p1; (2)this 指针 栗子: Person::Person(string new_name,unsigned new_age) { name=new_name; age=new_age; } 对于系统来讲,每次调用都相当于执行以下语句: this->name=new_name; this->age=new_age;
6.静态成员与友元
(1)静态数据成员与静态函数成员 静态数据成员
定义格式:static datatypy variablename;
静态数据成员必须在定义后立即初始化,静态数据成员不属于任何对象,所以其初始化不能由构造函数实现,其初始化通过域限定符在类外实现,语法如下: datatypy classname::avriablename=some_value;
注意:
- 数据型静态函数成员默认值为0,(若在类内有:static int count;即类外初始化count语句可以写为:int Person::count;但该语句不能省略。
- 静态数据成员不影响对象所占的内存空间。
- 当常函数成员同时又是静态函数成员时,即静态常函数成员时,其遵循静态成员的特点,需要在类外单独通过赋值语句来初始化。
- 静态数据成员属于整个类,不属于某个对象;类外初始化,声明在类内。
- 普通成员函数可以访问非静态和静态函数成员。
可以类外直访的有: 公有静态数据成员 公有普通数据成员
公有普通数据成员只可由对象访问,公有静态数据成员可以通过类/对象访问。
静态函数成员
静态函数成员和其他函数成员一样,属于类而非类的对象,但只能改变类的静态成员(数据/函数)其它函数成员则可以访问类的所有成员。
声明格式如下: static return_type Function_name(formal parameters list); 和类的其他函数成员一样,静态函数成员既可以定义在类内作为静态内联函数成员,也可在类内声明 在类外定义;在类外定义时static不用写。 例题:
class Person
{
public:
Person(string new_name,unsigned new_age);
Person(const Person& p);
Person(){count++;}
void set_name(string new_name);
void set_age(unsigned new_age);
string get_name(){
return name;
}
unsigned get_age(){
return age;
}
void disp();
static int getCount();
private:
string name;
unsigned age;
static int count; //定义静态数据成员count
};
int Person::count=0; //使用域限定符在类外初始化静态数据成员
Person::Person(string new_name,unsigned new_age)
{
name=new_name;
age=new_age;
count++;
}
Person::Person(const Person& p)
{
name=p.name;
age=p.age;
count++;
}
int Person::getCount() //静态函数成员在类外定义
{
return count;
}
int main()
{
Person p1,p2,p3;
Person p4("xiaoming",21),p5(p4);
cout<<"当前Person类对象的个数为:";
cout<<Person::getCount()<<endl;
return 0;
}
调试结果如下: 当前Person类对象的个数为:5
7.友元函数与友元类
通过友元机制,一个普通函数或者类的函数成员可以访问到封装在某一个类中的私有数据成员。如果友元是一般函数或者类的函数成员,成为友元函数;如果友元是一个类,则称为友元类,友元类中所有函数成员都是友元函数。 (1)友元函数 声明格式: friend return_type function_name(formal parameters list); 在友元函数体中可以通过对象名访问类的所有成员,包括public private protected 例题,友元函数的使用
class Complex
{
public:
Complex();
Complex(const Complex&);
Complex(double re,double im);
friend bool equal(Complex c1,Complex c2); //友元函数声明
void set_real(double re){real=re;}
void set_imag(double im){imag=im;}
double get_real(){return real;}
double get_imag(){return imag;}
void diap(){cout<<real<<"+"<<imag<<"i";}
private:
double real;
double imag;
};
Complex::Complex(double re,double im)
{
real=re;
imag=im;
}
Complex::Complex(const Complex& comp)
{
real=comp.real;
imag=comp.imag;
}
bool equal(Complex c1,Complex c2)
{
if((c1.real==c2.real)&&(c1.imag=c2.imag))
return true;
else
return false;
}
int main()
{
Complex c1(2,3),c2(3,4);
if(equal(c1,c2))
cout<<"这两个复数相等!"<<endl;
else
cout<<"这两个复数不相等!"<<endl;
return 0;
}
调试结果如下: 这两个复数不相等! 判断两个复数是否相等的函数,由于直接访问了复数类的private数据成员,避免了频繁调用函数成员,效率大大提高。
注意:
- 友元函数不是类的成员函数,它是类的朋友,使用时不需要类域限定符。
- 但是要在类中声明通过关键字friend声明,其声明的位置可以在类内任意位置。
- 友元函数可以在类内实现,也可以在类外实现,在类外实现不需要关键字friend
- C++中,不允许 构造函数 析构函数 虚函数 为友元函数。
友元函数和类的函数成员一样,可以访问类中的所有成员。不只是非函数成员,一个类的函数成员也可以是另一个类的友元。
函数成员作为友元:
class Student;
class Teacher
{
public:
//...
void gradeofcourse(Student& S);
private:
int numberofstu;
//...
};
class Student
{
public:
//...
friend void Teacher::gradeofcourse(Student& S);
private:
float grad;
Teacher* pT;
//...
};
void Teacher::gradeofcourse(Student& S)
{
s.grad=5; //直接访问到其他private数据成员grad
}
(2)友元类 当一个类中的所有函数成员都是另一个类的友元的时候,我们可以定义一个类为另一个类的友元。 例如,下面的代码是把整个Teacher类作为Student类的友元类,即Teacher类的所有函数成员都可以访问Student类的所有成员。
class Teacher
{
public:
//...
void gradeofcourse(Student& S); //前向声明
private:
int numberofstu;
//...
};
class Student
{
public:
//...
friend class Teacher;
private:
float grad;
//...
};
注意:
- 类是单向传递的,A是C的友元不等于C是A的友元。即Student类是Teacher类的友元,Teacher类的函数成员可以访问Student类成员,反之则不可以。
下一篇写继承了·