在C++中,指向类的指针是一种特殊的指针类型,用来指向类的对象。它的定义和普通指针类似,但需要指定它指向的是哪种类的对象。指向类的指针的主要作用包括动态分配内存、访问对象成员以及实现多态等。
指向类的指针的定义
指向类的指针的定义语法如下:
ClassName* pointerName;
其中,ClassName
是类的名称,pointerName
是指针变量的名称。
指向类的指针和普通指针在很多方面是相似的,因为它们都是指针,只不过指向的对象类型不同。以下是一些相似之处:
定义方式
两者的定义方式类似,只是类型不同。
int* intPtr; // 指向int类型的指针
double* doublePtr; // 指向double类型的指针
ClassName* classPtr; // 指向ClassName类对象的指针
存储地址
两者都用于存储某种数据类型的变量或对象的地址。
int a = 10;
intPtr = &a; // intPtr存储变量a的地址
ClassName obj;
classPtr = &obj; // classPtr存储对象obj的地址
指针运算
两者都可以进行指针运算,比如解引用、指针加减等。
*intPtr = 20; // 通过intPtr修改变量a的值
classPtr->memberFunc(); // 通过classPtr调用类对象的成员函数
动态内存分配
两者都可以使用new
和delete
进行动态内存分配和释放。
intPtr = new int;
*intPtr = 30;
delete intPtr;
classPtr = new ClassName();
delete classPtr;
从上述指向类的指针和普通指针在很多方面相似的操作中,我们可以看出,类和int
、double
、string
一样,都是一种数据类型。例如:
int* intPtr; // 指向int类型的指针
double* doublePtr; // 指向double类型的指针
ClassName* classPtr; // 指向ClassName类对象的指针
这里的ClassName
替换了基本数据类型int
、double
等,变成了用户自定义的数据类型。这种用户自定义的数据类型允许程序员定义自己的数据结构和操作这些数据的函数,提供了一种封装和组织代码的方式。通过类,用户可以创建具有特定属性(成员变量)和行为(成员函数)的对象。
指向类的指针的作用
- 动态分配内存:使用指针可以动态地分配类对象的内存,并在不再需要时释放内存,避免内存浪费。
- 访问对象成员:通过指针可以访问类对象的成员,包括成员变量和成员函数。
- 实现多态:在继承关系中,可以使用基类指针指向派生类对象,并调用派生类的重写函数,实现运行时多态。
举例说明
以下是一些简单的例子,演示了如何定义和使用指向类的指针。
动态分配内存
#include <iostream>
using namespace std;
// 定义一个简单的类
class Animal {
public:
void speak() {
cout << "Animal speaks" << endl;
}
};
int main() {
// 动态分配一个Animal对象的内存
Animal* animalPtr = new Animal();
// 使用指针访问对象的成员函数
animalPtr->speak();
// 释放分配的内存
delete animalPtr;
return 0;
}
运行结果如下:
Animal speaks
进程已结束,退出代码为 0
在这个例子中:
- 定义了一个名为
Animal
的类,包含一个成员函数speak
。 - 使用
new
运算符动态分配一个Animal
对象,并将其地址赋值给指针animalPtr
。 - 使用
animalPtr->speak()
语法通过指针调用对象的成员函数。 - 使用
delete
运算符释放分配的内存。
访问对象成员
#include "iostream"
using namespace std;
class Person{
public:
string name;
int age;
void Display(){
cout << "姓名:" << name << endl;
cout << "年龄:" << age << endl;
}
};
int main(){
Person p1;
p1.age = 18;
p1.name = "张三";
Person*p = &p1;
p->Display();
return 0;
}
运行结果如下:
姓名:张三
年龄:18
进程已结束,退出代码为 0
多态示例
以下是一个包含继承和多态的例子:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void speak() {
cout << "Animal speaks" << endl;
}
};
class Dog : public Animal {
public:
void speak() override {
cout << "Dog barks" << endl;
}
};
int main() {
Animal* animalPtr = new Dog();
// 使用基类指针调用派生类的重写函数
animalPtr->speak();
delete animalPtr;
return 0;
}
运行结果如下:
Dog barks
进程已结束,退出代码为 0
在这个例子中:
- 定义了一个基类
Animal
,其中的speak
函数被声明为virtual
,表示这是一个虚函数。 - 定义了一个派生类
Dog
,重写了基类的speak
函数。 - 使用
Animal
类的指针指向Dog
类的对象。 - 通过基类指针调用派生类的重写函数,实现了运行时多态。