一、this指针
在C++中,this 指针是一个隐式传递给每个成员函数的特殊指针,它指向当前对象的地址。通过 this 指针,可以在成员函数内部访问当前对象(对象是靠类创造的)的所有成员变量和成员函数。 在成员函数内部使用 this 指针:
this 指针是成员函数的一个隐式参数,指向调用该函数的对象 可以通过 this->member 或者直接 member 访问对象的成员变量和成员函数。
this 指针的作用
解决名称冲突:当成员变量和局部变量同名时,可以使用 this 指针来明确指定访问的是成员变量。 返回当前对象:在某些情况下,比如实现链式调用或者返回对象本身的情况下,可以返回 this 指针。 访问当前对象:在成员函数内部,可以使用 this 指针访问当前对象的所有成员。
#include < iostream>
class MyClass {
public:
int value;
MyClass(int val) : value(val) {}
void print() {
std::cout << "value = " << this->value << std::endl;
// 等同于 std::cout << "value = " << value << std::endl;
}
MyClass* getObject() {//定义了getObject()函数,返回值类型为MyClass*
// 返回指向当前对象的指针
return this;
}
};
int main() {
MyClass obj(42);
obj.print(); // 输出: value = 42
// 使用 this 指针访问对象的成员函数
MyClass* ptr = obj.getObject();
ptr->print(); // 输出: value = 42
return 0;
}
二、静态类成员
在 C++ 中,类的静态成员是所有对象共享的,这意味着它们不是属于某个特定实例的。静态成员可以是数据成员、成员函数或嵌套类。 static修饰成员(属性 方法)都只有一份,属于类,不属于对象,为所有对象所共享;没有对象他们也是存在的; 静态数据成员:
在类内部用 static 关键字声明。 在类外部定义和初始化。 所有类的实例共享相同的静态数据成员。
静态成员函数
在类内部用 static 关键字声明。 可以在类本身上调用,而不是在实例上调用。 只能访问其他静态成员(数据或函数)。
#include < iostream>
#include < string>
class Employee {
private:
static int nextEmployeeNumber; // 静态数据成员,用于跟踪下一个员工编号
int employeeNumber;
std::string name;
int age;
double salary;
std::string department;
public:
// 构造函数初始化员工对象
Employee(const std::string& name, int age, double salary, const std::string& department)
: employeeNumber(nextEmployeeNumber++), name(name), age(age), salary(salary), department(department) {}
// 静态成员函数获取下一个员工编号
static int getNextEmployeeNumber() {
return nextEmployeeNumber;
}
void display() const {
std::cout << "员工编号: " << employeeNumber << "\n"
<< "姓名: " << name << "\n"
<< "年龄: " << age << "\n"
<< "薪水: " << salary << "\n"
<< "部门: " << department << "\n";
}
};
// 初始化静态数据成员
int Employee::nextEmployeeNumber = 1;
int main() {
Employee emp1("John Doe", 30, 50000.0, "工程部");
Employee emp2("Jane Smith", 28, 60000.0, "市场部");
emp1.display();
emp2.display();
std::cout << "下一个员工编号: " << Employee::getNextEmployeeNumber() << "\n";
return 0;
}
三、const类成员
const 成员用于声明不可修改的成员变量或成员函数。使用 const 关键字,可以保证成员变量在初始化后不能被更改 ,或者保证成员函数不会修改类的成员变量 。 const 数据成员
必须在构造函数初始化列表中初始化 一旦初始化,就不能被修改
#include < iostream>
#include < string>
class Employee {
private:
const int employeeNumber; // const 数据成员
std::string name;
int age;
double salary;
std::string department;
public:
// 构造函数初始化 const 成员变量
Employee(int empNo, const std::string& name, int age, double salary, const std::string& department)
: employeeNumber(empNo), name(name), age(age), salary(salary), department(department) {}
void display() const {
std::cout << "员工编号: " << employeeNumber << "\n"
<< "姓名: " << name << "\n"
<< "年龄: " << age << "\n"
<< "薪水: " << salary << "\n"
<< "部门: " << department << "\n";
}
};
int main() {
Employee emp1(1, "John Doe", 30, 50000.0, "工程部");
emp1.display();
return 0;
}
const成员函数
用const关键字声明,保证函数不会修改类的成员变量 可以访问 const 和非 const 成员变量,但不能修改非 mutable 成员变量。 当一个对象被声明为 const 时,只能调用其 const 成员函数。 成员函数如果要被声明为 const,必须在函数声明的最后加上 const 关键字。这表示该成员函数不会修改对象的任何成员变量,除了那些被声明为 mutable 的变量。
#include < iostream>
#include < string>
class Employee {
private:
int employeeNumber;
std::string name;
int age;
double salary;
std::string department;
public:
// 构造函数初始化成员变量
Employee(int empNo, const std::string& name, int age, double salary, const std::string& department)
: employeeNumber(empNo), name(name), age(age), salary(salary), department(department) {}
// const 成员函数
void display() const {
std::cout << "员工编号: " << employeeNumber << "\n"
<< "姓名: " << name << "\n"
<< "年龄: " << age << "\n"
<< "薪水: " << salary << "\n"
<< "部门: " << department << "\n";
}
// const 成员函数不能修改类的成员变量
void setName(const std::string& newName) const {
// this->name = newName; // 错误: 不能在 const 成员函数中修改类成员
}
};
int main() {
Employee emp1(1, "John Doe", 30, 50000.0, "工程部");
emp1.display();
const Employee emp2(2, "Xiao Ming", 28, 40000.0, "工程部");
emp1.display(); // 只能调用 const 成员函数
return 0;
}
四、类的public private protected
类成员的访问控制通过 public、private 和 protected 关键字来实现。这些访问控制符决定了类的成员变量和成员函数的可访问性。 public
public 成员可以被类的任何代码访问,包括类的外部。 通常用于接口成员函数和需要被外部访问的数据成员。
private
private 成员只能被类的成员函数和友元函数(或友元类)访问,不能被类的外部代码直接访问。 通常用于隐藏实现细节,保护数据成员不被外部修改 。
protected
protected 成员可以被类本身及其子类 访问,但不能被类的外部代码直接访问。 通常用于继承关系中,需要对子类开放但对外部隐藏的成员。
继承访问控制表
基类成员访问权限 public 继承 protected 继承 private 继承 public public protected private protected protected protected private private 不可访问 不可访问 不可访问
public 继承 - 基类的 public 成员在派生类中保持 public 访问权限。 - 基类的 protected 成员在派生类中保持 protected 访问权限。 - 基类的 private 成员在派生类中不可访问。 protected 继承: - 基类的 public 成员在派生类中变为 protected 访问权限。 - 基类的 protected 成员在派生类中保持 protected 访问权限。 - 基类的 private 成员在派生类中不可访问。 private 继承: - 基类的 public 成员在派生类中变为 private 访问权限。 - 基类的 protected 成员在派生类中变为 private 访问权限。 - 基类的 private 成员在派生类中不可访问。
# include <iostream>
class Base {
public :
int publicVar;
protected :
int protectedVar;
private :
int privateVar;
} ;
class PublicDerived : public Base {
public :
void accessMembers ( ) {
publicVar = 1 ;
protectedVar = 2 ;
}
} ;
class ProtectedDerived : protected Base {
public :
void accessMembers ( ) {
publicVar = 1 ;
protectedVar = 2 ;
}
} ;
class PrivateDerived : private Base {
public :
void accessMembers ( ) {
publicVar = 1 ;
protectedVar = 2 ;
}
} ;
int main ( ) {
PublicDerived publicObj;
publicObj. publicVar = 10 ;
ProtectedDerived protectedObj;
PrivateDerived privateObj;
return 0 ;
}
五、友元friend
友元(Friend)是一种机制,允许一个类将其非公有成员的访问权限授予指定的函数或另一个类。友元函数和友元类可以访问类的私有(private)和保护(protected)成员。 友元函数 一个友元函数可以是类的成员函数,也可以是全局函数。它被声明在类的内部,但定义在类的外部。友元函数不属于类的成员,但它可以访问类的私有和保护成员。
#include < iostream>
class Box {
private:
double width;
public:
Box(double w) : width(w) {}
// 声明友元函数
friend void printWidth(Box box);
};
// 友元函数的定义
void printWidth(Box box) {
std::cout << "Width of box: " << box.width << std::endl;
}
int main() {
Box box(10.0);
printWidth(box); // 访问私有成员
return 0;
}
友元类 一个友元类可以访问另一个类的私有和保护成员。将一个类声明为友元类时,该友元类中的所有成员函数都可以访问被声明类的私有和保护成员。
#include < iostream>
class Engine {
private:
int horsepower;
public:
Engine(int hp) : horsepower(hp) {}
// 声明友元类
friend class Car;
};
class Car {
public:
void showHorsepower(Engine engine) {
std::cout << "Horsepower of engine: " << engine.horsepower << std::endl;
}
};
int main() {
Engine engine(300);
Car car;
car.showHorsepower(engine); // 访问私有成员
return 0;
}
在这个示例中,Car 类是 Engine 类的友元类,因此 Car 类的成员函数 showHorsepower 可以访问 Engine 的私有成员 horsepower。
使用友元的注意事项
友元关系是单向的。如果类 A 是类 B 的友元,A 可以访问 B 的私有和保护成员,但 B 不能访问 A 的私有和保护成员,除非 B 也声明 A 为友元。
友元关系不具传递性。如果类 A 是类 B 的友元,类 B 是类 C 的友元,这并不意味着类 A 是类 C 的友元。
友元破坏了封装性,因此应谨慎使用。
六、运算符重载
运算符重载是 C++ 中的一种功能,允许开发者为自定义的类定义特定的运算符行为,使这些运算符可以用于类的对象。运算符重载可以使代码更具可读性和易用性。 运算符重载通过定义特殊的成员函数或友元函数来实现。以下是运算符重载的基本语法:
class ClassName {
public:
// 成员函数的运算符重载//Op是重载的运算符
ReturnType operatorOp(const ClassName& rhs) const;
// 友元函数的运算符重载
friend ReturnType operatorOp(const ClassName& lhs, const ClassName& rhs);
};
重载+ 运算符
以下是一个重载 + 运算符的示例,该运算符用于向量(Vector)类的对象相加。
#include < iostream>
class Vector {
private:
double x, y;
public:
Vector(double x = 0, double y = 0) : x(x), y(y) {}
// 成员函数重载运算符+
Vector operator+(const Vector& rhs) const {
return Vector(x + rhs.x, y + rhs.y);
}
void display() const {
std::cout << "(" << x << ", " << y << ")\n";
}
};
int main() {
Vector v1(1.0, 2.0);
Vector v2(3.0, 4.0);
Vector v3 = v1 + v2; // 使用重载的+运算符
v3.display(); // 输出 (4.0, 6.0)
return 0;
}
重载运算符的时间类(Time)的示例
#include < iostream>
class Time {
private:
int hours;
int minutes;
public:
// 构造函数
Time(int h = 0, int m = 0) : hours(h), minutes(m) {}
// 加法运算符重载
Time operator+(const Time& rhs) const {
int totalMinutes = minutes + rhs.minutes;
int totalHours = hours + rhs.hours + totalMinutes / 60;
totalMinutes %= 60;
return Time(totalHours, totalMinutes);
}
// 等于运算符重载
bool operator==(const Time& rhs) const {
return (hours == rhs.hours && minutes == rhs.minutes);
}
// 小于运算符重载
bool operator<(const Time& rhs) const {
if (hours < rhs.hours) return true;
if (hours == rhs.hours && minutes < rhs.minutes) return true;
return false;
}
// 输出运算符重载
friend std::ostream& operator<<(std::ostream& out, const Time& t) {
out << t.hours << " hours, " << t.minutes << " minutes";
return out;
}
};
int main() {
Time t1(2, 45);
Time t2(1, 30);
Time t3 = t1 + t2;
std::cout << "t1: " << t1 << std::endl;
std::cout << "t2: " << t2 << std::endl;
std::cout << "t3 (t1 + t2): " << t3 << std::endl;
if (t1 == t2) {
std::cout << "t1 is equal to t2" << std::endl;
} else {
std::cout << "t1 is not equal to t2" << std::endl;
}
if (t1 < t3) {
std::cout << "t1 is less than t3" << std::endl;
} else {
std::cout << "t1 is not less than t3" << std::endl;
}
return 0;
}