首页 > 编程语言 >C++中的this指针、访问控制和构造函数

C++中的this指针、访问控制和构造函数

时间:2024-03-18 12:00:12浏览次数:16  
标签:访问 访问控制 成员 C++ class public Example 构造函数

C++中的this指针、访问控制和构造函数

this指针

在C++中,this指针是一个特殊的指针,它指向当前对象的地址。每个非静态成员函数(包括成员函数模板)都有一个this指针作为其隐含参数,这意味着在成员函数内部,this可以用来引用调用该成员函数的对象。this指针是自动传递给成员函数的,但在成员函数的参数列表中不可见。

this指针的用途

1. 明确成员访问

当局部变量(例如函数参数)的名称与类的成员变量名称相同时,可以使用this指针来区分它们,明确指出是对成员变量的访问。

class Example {
public:
    int value;
    void setValue(int value) {
        this->value = value; // 明确指出成员变量value
    }
};
2. 实现链式调用

this指针可以用于实现函数的链式调用。通过在成员函数的末尾返回*this,可以连续调用同一个对象上的其他成员函数。

class Example {
public:
    Example& setValue(int value) {
        this->value = value;
        return *this;
    }
    Example& doSomething() {
        // 操作
        return *this;
    }
};

Example obj;
obj.setValue(5).doSomething(); // 链式调用
3. 返回对象自身的引用或指针

在某些情况下,可能需要从成员函数返回调用它的对象自身的引用或指针,this提供了这种能力。

class Example {
public:
    Example* getThis() {
        return this; // 返回当前对象的指针
    }
};
4. 比较对象

this指针可以用于比较两个对象是否相同,即它们是否是内存中同一个对象的两个引用。

class Example {
public:
    bool compare(const Example& other) const {
        return this == &other; // 比较两个对象的地址
    }
};

注意事项

  • 在静态成员函数中不能使用this指针,因为静态成员函数不属于任何对象实例。
  • this是一个常量指针,不能修改它本身的值,即不能使this指向另一个对象,但可以修改this所指向的对象的成员。
  • 在构造函数和析构函数中使用this指针时需要小心,特别是在构造函数中,因为对象可能还没有完全构造完成。

总的来说,this指针在C++类的成员函数中自动可用,提供了一种访问调用函数的当前对象的便捷方式。

访问控制

在C++中,访问控制是面向对象编程的一个核心特性,它定义了如何访问类的成员(包括数据成员和成员函数)。访问控制旨在提高数据的封装性和安全性,通过限制对类成员的访问来防止外部代码随意修改对象的内部状态。

C++提供三种访问控制级别:publicprivateprotected,这些访问控制符可以用于类的成员变量和成员函数。

Public(公有)

  • public成员在任何地方都可以被访问,无论是类的内部还是外部。
  • 使用公有成员可以提供类的接口,允许外部代码通过这些接口与对象交互。

Private(私有)

  • private成员只能被其所在类的成员函数、友元函数和友元类访问。
  • 私有成员用于实现类的内部细节,隐藏类的实现,这是封装的一个重要方面。

Protected(受保护)

  • protected成员可以被其所在类的成员函数、友元函数和友元类访问,同时也可以被派生类访问。
  • protected访问控制符主要用于继承场景,允许派生类访问基类的成员,而不对外界公开。

访问控制与继承

在继承中,基类成员的访问权限在派生类中可能会有所变化,这取决于继承的类型(publicprotectedprivate继承):

  • 公有继承(public:基类的公有成员和受保护成员在派生类中保持其原有的访问级别,基类的私有成员在派生类中不可访问。
  • 保护继承(protected:基类的公有成员和受保护成员在派生类中都变成受保护成员,基类的私有成员在派生类中不可访问。
  • 私有继承(private:基类的公有成员和受保护成员在派生类中都变成私有成员,基类的私有成员在派生类中不可访问。

示例

class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};

class Derived : public Base {
    void func() {
        publicMember = 1;    // OK: public成员在派生类中可访问
        protectedMember = 2; // OK: protected成员在派生类中可访问
        // privateMember = 3; // 错误: private成员在派生类中不可访问
    }
};

int main() {
    Base b;
    b.publicMember = 1; // OK: public成员在外部可访问
    // b.protectedMember = 2; // 错误: protected成员在外部不可访问
    // b.privateMember = 3;   // 错误: private成员在外部不可访问
}

总之,C++中的访问控制是实现封装和继承的关键机制,它帮助程序员定义类成员的可见性和可访问性,以确保对象的内部状态被适当地保护。

构造函数

在C++中,构造函数是一种特殊的成员函数,它在创建类的对象时自动调用,用于初始化对象。构造函数的主要目的是为对象的成员变量设置初始值,并执行任何必要的设置或分配资源的操作。

构造函数的特点

  1. 与类同名:构造函数的名称必须与类名相同。
  2. 无返回类型:构造函数没有返回值,也不声明返回类型,连void也不写。
  3. 可以被重载:一个类可以有多个构造函数,它们通过参数列表的不同进行区分。
  4. 自动调用:构造函数在创建类的新对象时被自动调用。

构造函数的类型

  1. 默认构造函数:不带任何参数(也可以是所有参数都有默认值)的构造函数。如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数(只在没有其他构造函数时)。

    class Example {
    public:
        Example() { /* 默认构造函数体 */ }
    };
    
  2. 参数化构造函数:带有参数的构造函数,用于通过提供的参数初始化对象的成员变量。

    class Example {
    public:
        Example(int a, double b) { /* 构造函数体 */ }
    };
    
  3. 拷贝构造函数:以同类的对象作为参数的构造函数,用于初始化一个对象为另一个同类型对象的副本。

    class Example {
    public:
        Example(const Example& other) { /* 拷贝构造函数体 */ }
    };
    
  4. 移动构造函数(C++11引入):以同类对象的右值引用作为参数的构造函数,用于实现对象的移动语义,而非复制。

    class Example {
    public:
        Example(Example&& other) noexcept { /* 移动构造函数体 */ }
    };
    

构造函数的使用

  • 直接初始化:使用圆括号来初始化对象。

    Example obj1; // 调用默认构造函数
    Example obj2(5, 3.14); // 调用参数化构造函数
    
  • 拷贝初始化:使用等号和另一个对象来初始化新对象。

    Example obj3 = obj2; // 调用拷贝构造函数
    
  • 列表初始化(C++11引入):使用花括号来初始化对象。

    Example obj4{}; // 调用默认构造函数
    Example obj5{5, 3.14}; // 调用参数化构造函数
    
  • 移动初始化:使用std::move来强制调用移动构造函数。

    Example obj6 = std::move(obj5); // 调用移动构造函数
    

注意事项

  • 当定义了其他构造函数时,编译器不再自动生成默认构造函数。如果需要,默认构造函数必须显式定义。
  • 拷贝构造函数和移动构造函数对于实现值语义和管理资源非常重要。
  • 在构造函数中使用初始化列表(而非在构造函数体内赋值)通常更有效,特别是对于引用和常量成员变量。

构造函数是C++面向对象编程中的一个基本概念,正确理解和使用构造函数对于创建稳定、高效的C++程序至关重要。

struct和class

在C++中,struct(结构体)和class(类)都是用户自定义类型的关键构建块,它们提供了数据封装的功能。尽管structclass在很多方面非常相似,它们之间主要的区别在于默认的访问控制和继承类型。

默认访问控制和继承

  • struct的成员默认是public的,而class的成员默认是private的。这意味着,除非你明确指定访问级别,否则struct成员在外部是可访问的,而class成员则不是。
  • 当使用struct继承另一个structclass时,继承默认是public的;而在class中继承另一个class时,继承默认是private的。

用法和语义

  • struct:在C++中,struct通常用于定义简单的数据结构,其中主要包含数据成员而没有太多的函数成员(方法)。struct特别适用于当你想要打包一些数据在一起时,这与C语言中的struct用法类似。
  • classclass则通常用于定义更复杂的数据结构,它不仅包含数据成员,还包含操作这些数据的成员函数。class是实现面向对象编程(OOP)概念(如封装、继承、多态)的主要工具。

示例

下面是一个structclass的简单示例,以展示它们的基本用法:

struct Point {
    int x, y; // 默认public

    Point(int x, int y) : x(x), y(y) {} // 构造函数也是public
};

class Rectangle {
private:
    Point topLeft, bottomRight; // 默认private

public:
    Rectangle(const Point& tl, const Point& br) : topLeft(tl), bottomRight(br) {}

    void printCorners() { // 成员函数是public
        cout << "Top Left: (" << topLeft.x << ", " << topLeft.y << ")"
             << ", Bottom Right: (" << bottomRight.x << ", " << bottomRight.y << ")" << endl;
    }
};

int main() {
    Point p(0, 0); // 直接访问Point的成员变量
    Rectangle r(Point(0, 10), Point(10, 0)); // 通过构造函数初始化Rectangle
    r.printCorners(); // 调用Rectangle的成员函数
}

总结

尽管structclass在C++中非常相似,两者都可以用来定义含有数据成员和成员函数的类型,但它们在默认访问控制和默认继承类型上有所不同。选择使用struct还是class取决于你的特定需求,以及你对类型成员的默认访问权限的期望。一般而言,如果一个类型主要用于存储数据,并且你希望其成员默认为公有,那么使用struct可能更合适;如果你需要更多的封装和面向对象的特性,那么class将是更好的选择。

示例代码

#include <iostream>
#include <string>
using namespace std;

// 定义student类
class student {
private:
    string name; // 私有成员变量:学生的姓名
    double score; // 私有成员变量:学生的分数

public:
    // student类的构造函数
    // 当创建student对象时,此构造函数被自动调用以初始化对象
    student(string n, double s) {
        name = n; // 初始化姓名
        score = s; // 初始化分数
        cout << "构造函数\n"; // 打印构造函数被调用的消息
    }

    // 打印学生信息的成员函数
    void print() {
        // 使用this指针访问成员变量,打印学生的姓名和分数
        cout << this->name << " " << this->score << endl;
    }

    // 访问器函数:获取学生的姓名
    string get_name() { return name; }

    // 访问器函数:获取学生的分数
    double get_score() { return score; }

    // 修改器函数:设置学生的姓名
    void set_name(string n) { name = n; }

    // 修改器函数:设置学生的分数
    void set_score(double s) { score = s; }
};

int main() {
    // 创建一个名为stu的student对象,使用参数化构造函数初始化姓名和分数
    student stu("cz", 90);
    
    // 使用修改器函数更新stu对象的姓名和分数
    stu.set_name("Li ping");
    stu.set_score(78.5);
    
    // 调用stu对象的print函数打印更新后的学生信息
    stu.print();//print(&stu);

    // 使用访问器函数获取并打印stu对象的姓名和分数
    cout << stu.get_name() << " " << stu.get_score() << endl;

    return 0;
}

标签:访问,访问控制,成员,C++,class,public,Example,构造函数
From: https://blog.csdn.net/m0_73640344/article/details/136805040

相关文章

  • C++ 面试100问--完结(十一)
    C++中虚函数是怎么实现的?        每一个含有虚函数的类都至少有有一个与之对应的虚函数表,其中存放着该类所有虚函数对应的函数指针(地址),类的示例对象不包含虚函数表,只有虚指针;派生类会生成一个兼容基类的虚函数表。C++中纯虚函数的引入有什么目的?        纯......
  • C++学习笔记——004
    字符'0'和'\0'及整数0的区别:字符型变量用于存储一个单一字符,在C语言中用char表示,其中每个字符变量都会占用1个字节(8位二进制数)。字符'0':charc='0'; 它的ASCII码实际上是48,内存中存放表示:00110000。字符'\0':ASCII码为0,表示一个字符串结束的标志。这是转......
  • C++面试100问(十一)
    C++中STL中map和set的原理是什么?        map和set的底层实现主要通过红黑树来实现。C++中static和const的区别是什么?        const强调值不能被修改,而static强调唯一的拷贝。C++中关键字static有什么作用?        1)函数体内:static修饰的局部变......
  • 新书速览|轻松学C++编程:案例教学
    零负担学习C++语言的语法,轻松上手C++面向对象程序设计本书简介The19thAsianGames《轻松学C++编程:案例教学》从初学者的角度循序渐进地从C++语言的基础语法到高级语法进行讲解。全书使用生动的实例和图示,介绍C++面向对象程序设计的基础知识;进而通过案例详解类的高级应......
  • C++学习笔记——003
    malloc() 函数在C语言中就出现了,在C++中仍然存在,但建议尽量不要使用malloc()函数。new与malloc()函数相比,其主要的优点是,new不只是分配了内存,它还创建了对象。//一维数组动态分配,数组长度为mint*array=newint[m];//释放内存delete[]array;//二维数......
  • C++ Qt开发:QTcpSocket网络通信组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QTcpSocket组件实现基于TCP的网络通信功能。QTcpSocket和QTcpServer是Qt中用于实现基于T......
  • 05_C++数组指针和指针数组
    1.数组指针:当数组指针指向一个一维数组时,()优先级高,说明p是指针,指向一个整型的一维数组。这个一维数组的长度是n,也可以说p的步长为n。当p+1时,p指针会跨过n个整型数据的长度。2.指针数组:当定义一个一维数组时,系统会在内存中为改数组分配一个储存空间,其数组的变量名就是数组的首地址......
  • Qt/C++监控推流设备推流/延迟极低/实时性极高/rtsp/rtmp推流/hls/flv/webrtc拉流/调整
    一、前言算下来这个推流的项目作品写了有四年多了,最初第一个版本只有文件点播的功能,用的纯QTcpSocket通信实现,属于比较简单的功能。由于文件点播只支持文件形式的推流,不支持网络流或者本地设备采集,所以迫切需要打破这个瓶颈,而后加入核心的网络推流功能,这也是本项目的核心功能,不仅......
  • C/C++中的常用操作符与强制类型转换
    引言:在前两篇博客,我们详细介绍了C语言的基本数据类型和判断操作,相信大家对此已经有所掌握,在本篇博客,我们将继续介绍C语言中常用的几类操作符。一.算数操作符在写代码中,一定会涉及到计算问题,为此,C语言提供了一套操作符,分别是加法:+;减法:-;乘法:*;除法:/;取余数:%;我们依次结合代码讲解......
  • 2.3C++对象模型和this指针
    1、成员变量和成员函数分开存储在C++中,类内的成员变量和成员函数分开存储只有非静态成员变量才属于类的对象上空对象占用内存空间为1。C++编译器会为每个空对象也分配1个字节的空间,是为了区分空对象占内存的位置。每个空对象也应该有一个独一无二的内存地址。calssPerson{......