C++学习笔记

一、this指针

  1. 在C++中,this 指针是一个隐式传递给每个成员函数的特殊指针,它指向当前对象的地址。通过 this 指针,可以在成员函数内部访问当前对象(对象是靠类创造的)的所有成员变量和成员函数。
  2. 在成员函数内部使用 this 指针:
  • this 指针是成员函数的一个隐式参数,指向调用该函数的对象
  • 可以通过 this->member 或者直接 member 访问对象的成员变量和成员函数。
  1. 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;
}

二、静态类成员

  1. 在 C++ 中,类的静态成员是所有对象共享的,这意味着它们不是属于某个特定实例的。静态成员可以是数据成员、成员函数或嵌套类。
  2. static修饰成员(属性 方法)都只有一份,属于类,不属于对象,为所有对象所共享;没有对象他们也是存在的;
  3. 静态数据成员:
  • 在类内部用 static 关键字声明。
  • 在类外部定义和初始化。
  • 所有类的实例共享相同的静态数据成员。
  1. 静态成员函数
  • 在类内部用 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类成员

  1. const 成员用于声明不可修改的成员变量或成员函数。使用 const 关键字,可以保证成员变量在初始化后不能被更改,或者保证成员函数不会修改类的成员变量
  2. 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;
}

  1. 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

  1. 类成员的访问控制通过 public、private 和 protected 关键字来实现。这些访问控制符决定了类的成员变量和成员函数的可访问性。
  2. public
  • public 成员可以被类的任何代码访问,包括类的外部。
  • 通常用于接口成员函数和需要被外部访问的数据成员。
  1. private
  • private 成员只能被类的成员函数和友元函数(或友元类)访问,不能被类的外部代码直接访问。
    通常用于隐藏实现细节,保护数据成员不被外部修改
  1. protected
  • protected 成员可以被类本身及其子类访问,但不能被类的外部代码直接访问。
  • 通常用于继承关系中,需要对子类开放但对外部隐藏的成员。
  1. 继承访问控制表
基类成员访问权限public 继承protected 继承private 继承
publicpublicprotectedprivate
protectedprotectedprotectedprivate
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;
};

// public 继承
class PublicDerived : public Base {
public:
    void accessMembers() {
        publicVar = 1;     // 可访问
        protectedVar = 2;  // 可访问
        // privateVar = 3; // 不可访问
    }
};

// protected 继承
class ProtectedDerived : protected Base {
public:
    void accessMembers() {
        publicVar = 1;     // 可访问
        protectedVar = 2;  // 可访问
        // privateVar = 3; // 不可访问
    }
};

// private 继承
class PrivateDerived : private Base {
public:
    void accessMembers() {
        publicVar = 1;     // 可访问
        protectedVar = 2;  // 可访问
        // privateVar = 3; // 不可访问
    }
};

int main() {
    PublicDerived publicObj;
    publicObj.publicVar = 10; // 可访问
    // publicObj.protectedVar = 20; // 不可访问

    ProtectedDerived protectedObj;
    // protectedObj.publicVar = 10; // 不可访问
    // protectedObj.protectedVar = 20; // 不可访问

    PrivateDerived privateObj;
    // privateObj.publicVar = 10; // 不可访问
    // privateObj.protectedVar = 20; // 不可访问

    return 0;
}

五、友元friend

  1. 友元(Friend)是一种机制,允许一个类将其非公有成员的访问权限授予指定的函数或另一个类。友元函数和友元类可以访问类的私有(private)和保护(protected)成员。
  2. 友元函数
    一个友元函数可以是类的成员函数,也可以是全局函数。它被声明在类的内部,但定义在类的外部。友元函数不属于类的成员,但它可以访问类的私有和保护成员。
#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;
}

  1. 友元类
    一个友元类可以访问另一个类的私有和保护成员。将一个类声明为友元类时,该友元类中的所有成员函数都可以访问被声明类的私有和保护成员。
#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 的友元。
友元破坏了封装性,因此应谨慎使用。

六、运算符重载

  1. 运算符重载是 C++ 中的一种功能,允许开发者为自定义的类定义特定的运算符行为,使这些运算符可以用于类的对象。运算符重载可以使代码更具可读性和易用性。
  2. 运算符重载通过定义特殊的成员函数或友元函数来实现。以下是运算符重载的基本语法:
class ClassName {
public:
    // 成员函数的运算符重载//Op是重载的运算符
    ReturnType operatorOp(const ClassName& rhs) const;
    
    // 友元函数的运算符重载
    friend ReturnType operatorOp(const ClassName& lhs, const ClassName& rhs);
};

  1. 重载+ 运算符
  • 以下是一个重载 + 运算符的示例,该运算符用于向量(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;
}

  1. 重载运算符的时间类(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;
}

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值