C++:类和对象
对象是什么
在C++中,对象是面向对象编程(OOP)的核心概念之一。以下是对C++中对象的详细解释:
一、对象的定义
对象是类的实例化,是具体的、有形的实体。在C++中,定义一个类就相当于创建了一个新的类型(class类型),而对象则是这个类型的实例。每个对象都有自己的状态和行为,分别由类的数据成员和成员函数来表示。
二、对象的特性与行为
数据成员:对象的数据成员用于描述对象的状态。它们可以是任何有效的数据类型,包括基本类型(如int、float)和自定义类型。数据成员存储对象的属性和信息,可以被对象的成员函数访问和操作。
成员函数:对象的成员函数定义了对象的行为。它们可以访问和操作对象的数据成员,并提供对外的接口。成员函数可以是公有的、私有的或受保护的,用于控制对数据成员的访问权限。
三、对象的创建和使用
在C++中,可以通过以下方式创建和使用对象:
直接创建:使用类名和构造函数直接创建对象。例如,如果有一个名为MyClass的类,可以使用MyClass obj;来创建一个名为obj的对象。
使用初始化列表:在创建对象时,可以使用初始化列表来初始化对象的数据成员。这通常用于具有复杂数据成员或需要特定初始化顺序的类。
动态分配:可以使用new关键字在堆上动态分配对象。例如,MyClass* obj = new MyClass();会在堆上创建一个MyClass类型的对象,并返回一个指向该对象的指针。
四、对象间的交互
在C++中,对象之间可以通过成员函数、指针、引用等方式进行交互。例如,一个对象可以调用另一个对象的成员函数,或者通过指针或引用来访问另一个对象的数据成员。
五、对象的生命周期
对象的生命周期包括创建、使用和销毁三个阶段。在创建阶段,对象被分配内存并初始化。在使用阶段,对象的状态和行为可以通过其成员函数进行访问和修改。在销毁阶段,对象的内存被释放,析构函数被调用以执行必要的清理操作。
六、C++中的对象特性
C++中的对象还具有一些特殊的特性,如封装、继承、多态和抽象等。这些特性使得C++成为一种强大的面向对象编程语言,可以更好地组织和管理复杂的程序结构。
封装:将数据和操作数据的方法打包在一起,对外部隐藏对象的内部实现细节,只暴露必要的接口给外部使用。
继承:允许一个类(子类)继承另一个类(父类)的属性和行为,通过这种方式可以实现代码的重用和扩展。
多态:允许以统一的方式处理不同类型和不同类的对象,通过函数重载、运算符重载和虚函数实现多态性。
抽象:隐藏对象复杂性的某些部分,只显示对象的关键特征,使得对象更易于理解和使用。
#include <iostream>
#include <cstring>
using namespace std;
//设计一个学生类
class CStudent
{
public:
void inputdata(int s, string name, double score);
void outputdata() {
cout << this->sno << endl;
cout << this->sname << endl;
cout << this->dscore << endl;
}
private:
int sno;//学号
string sname; //姓名
double dscore; //分数
};
void CStudent::inputdata(int s, string name,double score)
{
sno = s;
sname = name;
dscore = score;
}
int main()
{
CStudent stu1;
stu1.inputdata(001,"hhh",99);
stu1.outputdata();
return 0;
}
类的嵌套
#include <iostream>
using namespace std;
class Ca
{
//定义内部类
class Cb
{
public:
int a;
int b;
};
public:
Cb b1;//定义对象
int setCb(int a, int b)
{
b1.a = a;
b1.b = b;
return 0;
}
int outputCb()
{
cout << b1.a << endl;
cout << b1.b << endl;
return 0;
}
};
int main()
{
Ca a;
a.setCb(1,9);
a.outputCb();
return 0;
}
成员函数重载
在C++中,成员函数重载(Member Function Overloading)是指同一个类中可以存在多个同名但参数列表不同的成员函数。这种特性允许我们根据传递的参数类型或数量来调用不同的函数实现,从而提高代码的灵活性和可读性。
成员函数重载的关键在于函数签名的不同,即参数列表(包括参数的类型、数量和顺序)必须有所区别。函数返回类型、函数名以及所属类名在重载中是不变的。
#include <iostream>
#include <string>
class MyClass {
public:
// 重载成员函数print,接受一个int参数
void print(int i) {
std::cout << "Integer: " << i << std::endl;
}
// 重载成员函数print,接受一个double参数
void print(double d) {
std::cout << "Double: " << d << std::endl;
}
// 重载成员函数print,接受一个std::string参数
void print(const std::string& str) {
std::cout << "String: " << str << std::endl;
}
// 重载成员函数print,不接受任何参数
void print() {
std::cout << "No arguments provided." << std::endl;
}
};
int main() {
MyClass obj;
// 调用不同重载的print函数
obj.print(42); // 调用接受int参数的print
obj.print(3.14); // 调用接受double参数的print
obj.print("Hello"); // 调用接受std::string参数的print
obj.print(); // 调用不接受任何参数的print
return 0;
}
通过指针引用对象的成员函数
#include <iostream>
using namespace std;
class Ctest
{
public:
int sum()
{
return x + y;
}
void setxy(int a, int b)
{
x = a;
y = b;
}
private:
int x,y;
};
int main() {
Ctest test;
test.setxy(1, 9);
int sum = test.sum();
cout << sum << endl;
Ctest* ptest;
ptest = &test;
int sum1 = ptest->sum();//通过指针引用对象的成员函数
cout << sum1 << endl;
return 0;
}
静态成员变量
#include <iostream>
using namespace std;
class CtestA
{
public:
CtestA(int a, int b, int c, int d) {
i = a;
j = b;
x = c;
y = d;
}
void output()
{
cout << x << " " << y << endl;
cout << i << " " << j << endl;
}
private:
int i, j;
static int x, y; //定义静态变量
};
//静态成员定性说明
int CtestA::x = 10;
int CtestA::y = 99;
int main() {
CtestA a(1, 2, 3, 4);
a.output();
return 0;
}
静态成员函数
可以直接访问静态成员变量
不能直接访问普通成员变量,因为没有隐含的this指针
#include <iostream>
using namespace std;
class CtestA
{
public:
static int sum()
{
//return i + j + x + y;//不能直接访问普通成员变量
return x + y;
}
CtestA(int a, int b, int c, int d) {
i = a;
j = b;
x = c;
y = d;
}
void output()
{
cout << x << " " << y << endl;
cout << i << " " << j << endl;
}
private:
int i, j;
static int x, y; //定义静态变量
};
//静态成员定性说明
int CtestA::x = 10;
int CtestA::y = 99;
int main() {
CtestA a(1, 2, 3, 4);
a.output();
int sum = CtestA::sum();
cout << sum << endl;
return 0;
}