Appearance
面向对象基础
面向对象编程(OOP)是C++的核心特性之一。本章将介绍类与对象、构造函数、析构函数、成员函数、访问控制等面向对象的基础概念。
类与对象
类的定义
cpp
#include <iostream>
#include <string>
using namespace std;
// 类的定义
// class 类名 { 成员 };
class Student {
// 访问修饰符
public: // 公有成员,可以在类外部访问
// 数据成员(属性)
string name;
int age;
double score;
// 成员函数(方法)
void display() {
cout << "姓名: " << name << endl;
cout << "年龄: " << age << endl;
cout << "分数: " << score << endl;
}
// 成员函数可以在类内定义,也可以在类外定义
void setInfo(string n, int a, double s);
private: // 私有成员,只能在类内部访问
string id; // 学号
protected: // 保护成员,只能在类内部和派生类中访问
string secret;
};
// 在类外定义成员函数
// 返回类型 类名::函数名(参数列表) { 函数体 }
void Student::setInfo(string n, int a, double s) {
name = n;
age = a;
score = s;
}
int main() {
// 创建对象
Student stu1; // 默认构造
// 访问公有成员
stu1.name = "张三";
stu1.age = 20;
stu1.score = 95.5;
// 调用成员函数
stu1.display();
// 使用成员函数设置信息
Student stu2;
stu2.setInfo("李四", 22, 88.0);
stu2.display();
// 不能访问私有成员
// stu2.id = "001"; // 错误:id是私有的
return 0;
}构造函数
cpp
#include <iostream>
#include <string>
using namespace std;
class Rectangle {
private:
double width;
double height;
public:
// ============ 默认构造函数 ============
// 无参构造函数
Rectangle() {
width = 1.0;
height = 1.0;
cout << "默认构造函数被调用" << endl;
}
// ============ 带参数的构造函数 ============
// 普通参数构造
Rectangle(double w, double h) {
width = w;
height = h;
cout << "带参数构造函数被调用" << endl;
}
// 单参数构造(可能隐式转换)
Rectangle(double size) {
width = size;
height = size;
cout << "单参数构造函数被调用" << endl;
}
// ============ 委托构造函数(C++11) ============
// 一个构造函数调用另一个构造函数
Rectangle(int size) : Rectangle((double)size, (double)size) {
cout << "委托构造函数被调用" << endl;
}
// ============ 拷贝构造函数 ============
Rectangle(const Rectangle& other) {
width = other.width;
height = other.height;
cout << "拷贝构造函数被调用" << endl;
}
// ============ 移动构造函数(C++11) ============
Rectangle(Rectangle&& other) noexcept {
width = other.width;
height = other.height;
other.width = 0;
other.height = 0;
cout << "移动构造函数被调用" << endl;
}
// ============ 成员函数 ============
double area() {
return width * height;
}
void display() {
cout << "宽: " << width << ", 高: " << height << endl;
}
};
int main() {
// 调用不同的构造函数
cout << "===== 创建对象 =====" << endl;
Rectangle r1; // 默认构造
Rectangle r2(3.0, 4.0); // 带参数构造
Rectangle r3(5.0); // 单参数构造
Rectangle r4(6); // 委托构造
r1.display();
r2.display();
r3.display();
r4.display();
// 拷贝构造
cout << "\n===== 拷贝构造 =====" << endl;
Rectangle r5 = r2; // 拷贝构造
Rectangle r6(r2); // 拷贝构造
// 移动构造
cout << "\n===== 移动构造 =====" << endl;
Rectangle r7 = move(r2); // 移动构造
// 隐式转换(可能不期望)
cout << "\n===== 隐式转换 =====" << endl;
Rectangle r8 = 10.0; // 隐式调用单参数构造
// 使用explicit防止隐式转换
// explicit Rectangle(double size); // 加在声明前
return 0;
}成员初始化列表
cpp
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string name;
int age;
const int id; // const成员必须在初始化列表初始化
int& ref; // 引用成员必须在初始化列表初始化
public:
// 使用成员初始化列表
// 比在构造函数体内赋值更高效
Person(string n, int a, int i, int& r)
: name(n), age(a), id(i), ref(r) // 初始化列表
{
cout << "Person构造函数" << endl;
}
// 初始化列表的顺序由成员声明的顺序决定,不是初始化列表的顺序
// 建议:初始化列表顺序与成员声明顺序一致
void display() {
cout << "姓名: " << name << endl;
cout << "年龄: " << age << endl;
cout << "ID: " << id << endl;
cout << "引用: " << ref << endl;
}
};
class Student {
private:
string name;
int scores[3]; // 数组成员
public:
// 数组成员的初始化
Student(string n, int s1, int s2, int s3)
: name(n), scores{s1, s2, s3} // C++11数组初始化
{
cout << "Student构造函数" << endl;
}
void display() {
cout << "姓名: " << name << endl;
cout << "成绩: ";
for (int s : scores) {
cout << s << " ";
}
cout << endl;
}
};
class Base {
public:
Base(int value) {
cout << "Base构造: " << value << endl;
}
};
class Derived : public Base {
private:
int data;
public:
// 先调用基类构造,再初始化成员
Derived(int v) : Base(v), data(v) {
cout << "Derived构造" << endl;
}
};
int main() {
int value = 100;
Person p("张三", 25, 1, value);
p.display();
cout << endl;
Student s("李四", 90, 85, 95);
s.display();
cout << endl;
Derived d(42);
return 0;
}析构函数
cpp
#include <iostream>
#include <string>
using namespace std;
class Resource {
private:
string name;
int* data; // 动态分配的资源
public:
// 构造函数
Resource(string n) : name(n) {
data = new int[100]; // 分配资源
cout << "构造: " << name << endl;
}
// 析构函数
// 对象销毁时自动调用
// 用于释放资源
~Resource() {
delete[] data; // 释放资源
cout << "析构: " << name << endl;
}
void use() {
cout << "使用资源: " << name << endl;
}
};
class Container {
private:
Resource* res;
public:
Container() {
res = new Resource("容器资源");
cout << "Container构造" << endl;
}
~Container() {
delete res; // 释放内部资源
cout << "Container析构" << endl;
}
};
// 函数内创建对象
void testFunction() {
cout << "===== 函数开始 =====" << endl;
Resource local("局部对象");
local.use();
cout << "===== 函数结束 =====" << endl;
// local在这里被销毁
}
int main() {
// 局部对象
cout << "===== 局部对象 =====" << endl;
{
Resource r1("对象1");
Resource r2("对象2");
r1.use();
r2.use();
} // r2先析构,r1后析构(后构造的先析构)
cout << "\n===== 动态对象 =====" << endl;
Resource* ptr = new Resource("动态对象");
ptr->use();
delete ptr; // 手动释放,调用析构函数
cout << "\n===== 函数调用 =====" << endl;
testFunction();
cout << "\n===== 包含资源的对象 =====" << endl;
{
Container c;
} // c析构时自动释放内部资源
return 0;
}访问控制
cpp
#include <iostream>
#include <string>
using namespace std;
class BankAccount {
private: // 私有成员:只能在类内部访问
string accountNumber;
double balance;
string password;
// 私有成员函数
bool verifyPassword(string pwd) {
return pwd == password;
}
protected: // 保护成员:类内部和派生类可访问
string ownerName;
public: // 公有成员:任何地方都可访问
// 构造函数
BankAccount(string owner, string accNum, string pwd, double initial)
: ownerName(owner), accountNumber(accNum), password(pwd), balance(initial) {}
// 公有接口函数(getter)
string getOwner() const {
return ownerName;
}
string getAccountNumber() const {
return accountNumber;
}
double getBalance() const {
return balance;
}
// 公有接口函数(setter)
bool setPassword(string oldPwd, string newPwd) {
if (verifyPassword(oldPwd)) {
password = newPwd;
return true;
}
return false;
}
// 存款
void deposit(double amount) {
if (amount > 0) {
balance += amount;
cout << "存款成功: " << amount << endl;
}
}
// 取款
bool withdraw(double amount, string pwd) {
if (!verifyPassword(pwd)) {
cout << "密码错误" << endl;
return false;
}
if (amount > 0 && amount <= balance) {
balance -= amount;
cout << "取款成功: " << amount << endl;
return true;
}
cout << "余额不足或金额无效" << endl;
return false;
}
// 显示账户信息
void displayInfo() {
cout << "户主: " << ownerName << endl;
cout << "账号: " << accountNumber << endl;
cout << "余额: " << balance << endl;
}
};
// 派生类可以访问保护成员
class SavingsAccount : public BankAccount {
private:
double interestRate;
public:
SavingsAccount(string owner, string accNum, string pwd, double initial, double rate)
: BankAccount(owner, accNum, pwd, initial), interestRate(rate) {}
void applyInterest() {
double interest = getBalance() * interestRate;
deposit(interest);
cout << "利息已入账: " << interest << endl;
}
// 可以访问保护成员
void displayOwner() {
cout << "账户持有人: " << ownerName << endl;
}
};
int main() {
BankAccount account("张三", "1234567890", "1234", 1000.0);
// 公有成员可以直接访问
account.displayInfo();
// 通过公有接口访问私有数据
cout << "\n当前余额: " << account.getBalance() << endl;
// 存款
account.deposit(500.0);
cout << "存款后余额: " << account.getBalance() << endl;
// 取款
account.withdraw(200.0, "1234");
cout << "取款后余额: " << account.getBalance() << endl;
// 错误的密码
account.withdraw(100.0, "wrong");
// 不能直接访问私有成员
// account.balance = 0; // 错误
// account.password = "new"; // 错误
// 不能直接访问保护成员
// account.ownerName = "李四"; // 错误
cout << "\n===== 储蓄账户 =====" << endl;
SavingsAccount savings("李四", "9876543210", "5678", 5000.0, 0.03);
savings.displayOwner();
savings.applyInterest();
return 0;
}静态成员
cpp
#include <iostream>
#include <string>
using namespace std;
class Counter {
private:
int value;
// 静态数据成员:所有对象共享
static int count; // 声明
public:
Counter() : value(0) {
count++; // 每创建一个对象,count加1
}
~Counter() {
count--; // 每销毁一个对象,count减1
}
// 静态成员函数:只能访问静态成员
static int getCount() {
// value = 10; // 错误:不能访问非静态成员
return count;
}
// 常量静态成员(C++17前需要在类外定义)
static const int MAX_VALUE = 100;
// C++11:constexpr静态成员
static constexpr double PI = 3.14159;
void display() {
cout << "value = " << value << endl;
}
};
// 静态成员的定义和初始化(在类外)
int Counter::count = 0;
class Singleton {
private:
static Singleton* instance;
// 私有构造函数
Singleton() {
cout << "Singleton创建" << endl;
}
public:
// 禁止拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 获取唯一实例
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
void doSomething() {
cout << "Singleton工作" << endl;
}
};
Singleton* Singleton::instance = nullptr;
int main() {
cout << "初始count: " << Counter::getCount() << endl;
{
Counter c1;
cout << "创建c1后count: " << Counter::getCount() << endl;
Counter c2;
cout << "创建c2后count: " << Counter::getCount() << endl;
Counter c3;
cout << "创建c3后count: " << Counter::getCount() << endl;
}
cout << "离开作用域后count: " << Counter::getCount() << endl;
// 访问静态常量
cout << "\nMAX_VALUE: " << Counter::MAX_VALUE << endl;
cout << "PI: " << Counter::PI << endl;
// 单例模式
cout << "\n===== 单例模式 =====" << endl;
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
cout << "s1 == s2: " << (s1 == s2) << endl; // true
s1->doSomething();
return 0;
}友元
cpp
#include <iostream>
#include <string>
using namespace std;
class Vector; // 前向声明
class Point {
private:
double x, y;
public:
Point(double x = 0, double y = 0) : x(x), y(y) {}
void display() {
cout << "(" << x << ", " << y << ")" << endl;
}
// 声明友元函数
friend Point add(const Point& a, const Point& b);
// 声明友元类
friend class Vector;
// 声明另一个类的成员函数为友元
friend void transform(Point& p, const Vector& v);
};
// 友元函数:可以访问类的私有成员
Point add(const Point& a, const Point& b) {
return Point(a.x + b.x, a.y + b.y); // 可以访问私有成员
}
class Vector {
private:
double dx, dy;
public:
Vector(double dx = 0, double dy = 0) : dx(dx), dy(dy) {}
// 友元类的所有成员函数都可以访问Point的私有成员
Point move(const Point& p) {
return Point(p.x + dx, p.y + dy); // 可以访问Point的私有成员
}
void display() {
cout << "Vector(" << dx << ", " << dy << ")" << endl;
}
};
// 另一个类的成员函数作为友元
void transform(Point& p, const Vector& v) {
p.x += v.dx;
p.y += v.dy;
}
int main() {
Point p1(1, 2);
Point p2(3, 4);
cout << "p1: ";
p1.display();
cout << "p2: ";
p2.display();
// 使用友元函数
Point p3 = add(p1, p2);
cout << "\np1 + p2 = ";
p3.display();
// 使用友元类
Vector v(10, 20);
Point p4 = v.move(p1);
cout << "\np1移动后: ";
p4.display();
// 使用友元成员函数
transform(p1, v);
cout << "p1变换后: ";
p1.display();
return 0;
}本章小结
本章学习了:
- 类与对象:类的定义、对象的创建和使用
- 构造函数:默认构造、带参构造、拷贝构造、移动构造
- 成员初始化列表:高效初始化成员
- 析构函数:释放资源
- 访问控制:public、private、protected
- 静态成员:静态数据成员和静态成员函数
- 友元:友元函数和友元类
下一章,我们将学习面向对象进阶,了解继承、多态和虚函数。
