#include
using namespace std;
class Student
{
private:
int m_nNumber;
char* m_cName;
public:
Student(int nNum, const char* cName);
void show();
void setNumber(int nNum);
void setName(const char* cName);
// 程序默认的拷贝构造函数,是浅拷贝
//Student(const Student& s)
//{
// m_nNumber = s.m_nNumber;
// m_cName = s.m_cName;
//}
// 总结:
// 浅拷贝只能复制基本的数据类型,而且不会相互影响
// 如果是带指针的属性,就需要深拷贝来完成,要自定义一个拷贝构造函数,给带指针的内容重新开辟空间
// 声明自定义的拷贝构造函数来实现深拷贝
Student(const Student& s);
};
Student::Student(int nNum, const char* cName)
{
m_nNumber = nNum;
// 申请动态内存来保存字符串
m_cName = new char[strlen(cName) + 1];
strcpy_s(m_cName, strlen(cName) + 1, cName);
}
Student::Student(const Student& s)
{
m_nNumber = s.m_nNumber; // 普通变量直接复制即可
// 实现拷贝对象的时候重新开辟空间来存储字符串,保证源对象和当前对象字符串的地址不同
m_cName = new char[strlen(s.m_cName) + 1];
strcpy_s(m_cName, strlen(s.m_cName) + 1, s.m_cName);
}
void Student::setNumber(int nNum)
{
m_nNumber = nNum;
}
void Student::setName(const char* cName)
{
strcpy_s(m_cName, strlen(cName)+1, cName);
}
void Student::show()
{
if (m_cName != NULL)
{
cout << "学号:" << m_nNumber << "\t";
cout << "姓名:" << m_cName << endl;
}
}
int main()
{
Student s1(202401, "gaiya");
Student s2(s1); // 如果定义了拷贝构造函数就用定义的,如果没定义就用默认的
s1.show();
s2.show();
cout << "-----------------------" << endl;
s2.setNumber(202402);
s2.setName("yousi");
s1.show();
s2.show();
return 0;
}
组合类的构造过程
如果内嵌对象的类有无参的构造函数,就在组合类构造函数的初始化表中可以不提供对该内嵌对象的初始化参数,编译器会自动调用无参构造函数来创建内嵌对象。如果内嵌对象的类有带参的构造函数,就在组合类构造函数的初始化表中必须提供对该内嵌对象的初始化参数,如果类中有多个内嵌对象,则组合类构造函数的执行顺序如下:
1.按内嵌对象的声明顺序依次调用内嵌对象的构造函数
2.执行组合类本身的构造函数
示例
#include
using namespace std;
// 定义一个圆类
class Point
{
private:
int x;
int y;
public:
Point(int x = 0, int y = 0); // 构造函数
Point(const Point& p); // 拷贝构造
int getX();
int getY();
};
Point::Point(int x1, int y1)
{
x = x1;
y = y1;
cout << x << "," << y << "正在构造" << endl;
}
Point::Point(const Point& p)
{
x = p.x;
y = p.y;
}
int Point::getX()
{
return x;
}
int Point::getY()
{
return y;
}
class Circle
{
private:
const double PI; // 圆周率
Point center; // 圆心 嵌套圆类即类的组合
double radius; // 半径
public:
// 构造函数
Circle(const Point& p, double r);
// 拷贝构造
Circle(const Circle& c);
void show(); // 展示圆心坐标和半径
};
// 常量成员只能使用列表初始化的方式来进行赋值
Circle::Circle(const Point& p, double r) :PI(3.1415), center(p)
{
radius = r;
}
Circle::Circle(const Circle& c):PI(c.PI)
{
radius = c.radius;
center = c.center;
}
void Circle::show()
{
cout << "圆心:" << center.getX() << "," << center.getY() << endl;
cout << "半径:" << radius << endl;
}
class Triangle
{
// 如果出现多个内嵌对象,构造的时候按照声明的顺序来完成构造,不论初始化的顺序是否相同,不影响构造顺序
private:
Point point2;
Point point1;
Point point3;
public:
Triangle(const Point& p1, const Point& p2, const Point& p3);
Triangle(int a, int b, int c, int d, int e, int f);
void show();
};
// 如果传入的是对象,在传入之前就已经构造完成了,和类中的对象声明顺序就没关系了
Triangle::Triangle(const Point& p1, const Point& p2, const Point& p3):point3(p1),point2(p2),point1(p3)
{
cout << "Triangle正在构造" << endl;
}
// 如果传入的是值,在传入值之后才进行对象的创建,那么就按照对象的声明顺序来进行初始化
Triangle::Triangle(int a, int b, int c, int d, int e, int f):point3(e,f), point2(c,d), point1(a,b)
{
cout << "Triangle正在构造" << endl;
}
void Triangle::show()
{
cout << "第一个点:" << point1.getX() << "," << point1.getY() << endl;
cout << "第二个点:" << point2.getX() << "," << point2.getY() << endl;
cout << "第三个点:" << point3.getX() << "," << point3.getY() << endl;
}
int main()
{
Triangle t(20, 30, 40, 50, 60, 70);
t.show();
//Point p1(20, 30);
//Point p2(30, 40);
//Point p3(50, 60);
//Triangle t(p1, p2, p3);
//t.show();
return 0;
}
声明格式:
类中声明:static 类型标识符 静态数据成员名
类外定义:类型标识符 类名::静态数据成员名 = 初始值;
使用类名访问静态属性:类名::静态数据成员名
静态成员函数:
特点:
代码实现
#include
using namespace std;
// 封装一个类,成员数据有学生的编号、姓名、年龄、学生总计
// 编号要按照2024001 2024002 2024003,姓名是字符数组类型,年龄int类型
// 编号自动生成,创建对象的时候只提供姓名和年龄
// 使用getCount() 方法可以获取学生的总数
class Student
{
private:
// 定义静态数据成员来计算对象的个数
static int count;
int number; // 学号
char name[20]; // 姓名
int age; // 年龄
public:
Student(const char* n, int a);
int getNumber()
{
return number;
}
char* getName()
{
return name;
}
int getAge()
{
return age;
}
//int getCount()
//{
// return count;
//}
// 将getCount修改为静态成员函数
static int getCount()
{
// 静态成员函数不能访问非静态成员
// cout << number;
return count;
}
};
// 在类外对静态数据成员初始化
int Student::count = 0;
Student::Student(const char* n, int a)
{
age = a;
strcpy_s(name, n);
count++;
number = 2024000 + count;
}
int main()
{
// 学号要自动生成,创建对象的时候需要提供姓名和年龄
cout << Student::getCount() << endl;
Student s1("张三", 19);
cout << Student::getCount() << endl;
Student s2("李四", 20);
cout << Student::getCount() << endl;
Student s3("王五", 21);
cout << Student::getCount() << endl;
cout << s1.getNumber() << "\t" << s1.getName() << "\t" << s1.getAge() << endl;
cout << s2.getNumber() << "\t" << s2.getName() << "\t" << s2.getAge() << endl;
cout << s3.getNumber() << "\t" << s3.getName() << "\t" << s3.getAge() << endl;
//cout << "学生的总数:" << s1.getCount() << "," << s2.getCount() << "," << s3.getCount() << endl;
return 0;
}
使用常成员函数的注意点:
代码实现:
#include
using namespace std;
class Student
{
private:
// 定义静态数据成员来计算对象的个数
static int count;
int number; // 学号
char name[20]; // 姓名
int age; // 年龄
public:
Student(const char* n, int a);
int getNumber()
{
return number;
}
char* getName()
{
return name;
}
int getAge()
{
return age;
}
static int getCount()
{
return count;
}
// 普通成员不能被常对象访问
//void output()
//{
// cout << "执行成员函数" << endl;
// cout << "这个对象的属性有:" << number << "\t" << name << endl;
//}
// 常成员函数可以被常对象访问
void output() const;
};
// 在类外对静态数据成员初始化
int Student::count = 0;
void Student::output() const {
cout << "执行成员函数" << endl;
cout << "这个对象的属性有:" << number << "\t" << name << endl;
}
Student::Student(const char* n, int a)
{
age = a;
strcpy_s(name, n);
count++;
number = 2024000 + count;
}
int main()
{
// 定义了一个常对象
const Student s1("星星队长", 99);
// 常对象不能调用普通成员函数
// s1.output();
// 常对象可以调用静态成员函数
cout << s1.getCount() << endl;
s1.output();
return 0;
}
对象数组:
定义:类名 数组名[常量表达式];
访问成员:数组名[下标].成员名
对象指针:
定义:类名 *对象指针名
代码实现:
#include
using namespace std;
class Student
{
private:
int number;
char name[10];
int age;
public:
Student(int id, const char* s_name, int a)
{
number = id;
strcpy_s(name, s_name);
age = a;
}
int getAge()
{
return age;
}
void show()
{
cout << number << "\t" << name << "\t" << age << endl;
}
};
int main()
{
方式1:先创建对象,再添加到数组中
//Student s1(10001, "张三", 20);
//Student s2(10002, "张四", 21);
//Student s3(10003, "张五", 22);
//Student s[3] = { s1,s2,s3 };
对象数组
//Student s[3] = {
// Student(10001, "黑猫警长", 18),
// Student(10002, "霹雳火", 16),
// Student(10003, "白鸽警官", 18)
//};
// 对象指针
//Student *p = new Student(10001, "黑猫警长", 18);
//Student s1(10002, "霹雳火", 16);
//p = &s1;
// 定义一个Student的指针数组来存放Student对象的地址
Student* p[3];
p[0] = new Student(10001, "黑猫警长", 18);
p[1] = new Student(10002, "霹雳火", 16);
p[2] = new Student(10003, "白鸽警官", 18);
double sum = 0;
for (int i = 0; i < 3; i++)
{
// []和.的优先级比较高,*的优先级在第二级,所以会先执行[]和. , 要将(*p[i]) 当做整体来对待,解引用之后获取对象再用. 来调用成员
// 建议直接用->来获取元素
sum += (*p[i]).getAge();
p[i]->show();
}
cout << "平均年龄:" << sum / 3 << endl;
for (int i = 0; i < 3; i++)
{
delete p[i];
p[i] = NULL;
}
return 0;
}
代码实现:
#include
using namespace std;
class ThisClass
{
int x;
int y;
public:
ThisClass(int x = 0, int y = 0)
{
// this代表指向当前对象的x和y成员,后面的x和y才是形参
this->x = x;
this->y = y;
}
void show()
{
cout << x << "," << y << endl;
}
};
int main()
{
ThisClass t1;
t1.show();
return 0;
}