C++ this指针原理与可变参数、友元详解

远山来客
远山来客
发布时间:2026-10-15 | 3人浏览过
原创

C++编程中经常需要处理对象的内部状态与特殊调用场景。本文将详解this指针的常量属性,演示如何利用stdarg.h实现可变参数,剖析static静态成员的初始化规则,并通过具体示例掌握友元函数与友元类对私有成员的访问权限。

this指针的本质与const修饰

this指针是类方法中隐式的指向当前对象的指针。在C++中,它本质上是一个常量指针常量(const T* const),这意味着:

  • 地址不可修改:不能改变this指向的对象内存地址。
  • 所指值默认不可修改:除非该方法是mutable的或者对象本身非常量,否则通常不允许通过this修改成员变量的值。

当方法声明带有 const 后缀时,this的类型严格等价于 const ClassName* const,此时不仅不能修改地址,连成员变量的值也不允许更改。

void changeAction() const {
    // 报错:无法给只读指针赋值
    // this = 0x43563;
    
    // 报错:const对象成员变量不可写
    // this->age = 80;
}

static静态成员的正确初始化

静态成员变量属于类而非特定对象,因此不能在类的构造函数或头文件声明处直接初始化。必须在类外部进行定义和初始化,且通常不需要重复使用 static 关键字。

class Douluo {
public:
    static char * name;
    // ... 构造及其他方法 ...
};

/*静态变量正确初始化姿势:类外初始化*/
char* Douluo::name = "唐三";

int main() {
    Douluo douluo;
    // 静态方法可以通过类名直接调用
    Douluo::update(); 
    return 0;
}

注意:Douluo::name 只能用于调用或读取,不能在 main 或其他作用域内再次对其进行“初始化”赋值(即重新定义类型),否则会引发编译错误。

C++可变参数的应用

处理数量不确定的参数时,C++提供了基于宏的可变参数支持。使用前需引入 <stdarg.h> 头文件。

第1步:定义函数签名

第一个参数通常为固定长度或计数,后续使用 ... 占位。例如: void add(int count, ...)

第2步:初始化参数列表

声明 va_list 类型的变量,并使用 va_start 配合倒数第二个固定参数开始遍历:

va_list vp; 
va_start(vp, count); // count是最后一个非可变参数

第3步:获取参数并清理

使用 va_arg 按指定类型逐个提取参数。如果超出范围继续获取,结果通常是不确定的或为0。最后必须调用 va_end 结束宏的使用。

void add(int count, ...) {
    va_list vp; 
    va_start(vp, count);
    for (int i = 0; i < count; ++i) {
        int number = va_arg(vp, int);
        cout << number << endl;
    }
    va_end(vp);
}

int main() {
    add(3, 6, 7, 8);
    return 0;
}

友元函数与友元类

为了打破封装限制,允许特定的外部函数或类访问私有成员,C++引入了 friend 机制。

友元函数:绕过Getter/Setter

如果在类外部定义了非成员函数,需要在类内部将其声明为 friend。该函数即可直接访问类的所有私有和保护成员,无需借助公共接口。

class Person {
private:
    int age = 0;
public:
    Person(int age) { this->age = age; }
    friend void updateAge(Person * person, int newAge); // 声明友元
};

// 实现函数可直接操作私有变量
void updateAge(Person* person, int newAge) {
    person->age = newAge;
}

int main(){
    Person person(30);
    updateAge(&person, 31);
    cout << person.getAge() << endl; // 输出 31
}

友元类:全局授权

类似于Java中的反射或管理类,若将另一个类声明为友元,则该类的所有成员函数都可以访问原类的私有数据。这在框架设计或视图管理类中较为常见。

class ImageView {
private:
    int viewSize;
    friend class ViewManager; // 友元类
};

class ViewManager {
public:
    void setSize(ImageView& iv, int size) {
        // 即使viewSize是private,也能直接访问
        iv.viewSize = size;
    }
};
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表