[C++ Primer] C7(重点章节)

C7: Class

7.1 Define a class

介绍如何定义一个类以及类的成员。类的成员包括数据成员和成员函数,数据成员表示类的状态,而成员函数则表示类的行为。在定义一个类时,需要确定类的数据成员和成员函数的访问权限

```
    class A {
     public: // 习惯给public加一个空格
        int a_; // 给成员变量一个下划线

        // constructor
        explicit A (int value) : a_(value) {}

        // const A* const this (top level const, the object cannot be modified)
        void func() {
            cout << this->a_ << endl;
        }
    };

    int main(){
        A a(10);
        A a1 = A(10);

        // A a2 = 10; 
        // if no explicit exist: cast to A a2 = A(10)
        
        // if explicit exists, we have to write A a2 = A(10)
        A a2 = A(10);
    }

```

7.2. Access Control and Encapsulation

C++ 提供了三种访问控制方式:public、protected 和 private。public 成员可以被类的外部访问,protected 成员可以被类的子类和类内部访问,private 成员只能被类的内部访问。访问控制可以帮助控制类的接口,提高代码的安全性和可维护性

// Acess control: 
// public
// private
// scope , range
// if I define a friend class/func, I can access your private element directly。但是破坏了封装原则
```
    // declaration 声明有这样一个函数
    void func1(int, bool);

    class Parent_class {
        friend void func1(int, bool); // 定义一个友元函数
    private:
        int a_;
        bool b_;

        Parent_class(int a, bool b) : a_(a), b_(b) {}

        void func() {
            cout << "in parent class";
        }
    };

    // define 定义具体的函数实施
    void func1(int a, bool b) {
        Parent_class parent_class(1, false);
        parent_class.func();
        cout << parent_class.a_ << endl;
    }
```

7.3. Additional Class Features

构造函数可以有多种重载形式,可以在创建对象时进行初始化,而析构函数在对象销毁时自动调用

可变数据成员(mutable)是指可以在 const 成员函数中被修改的数据成员

静态类成员(static)是指属于类本身而不是类的对象的数据成员或函数成员。静态成员变量只有一个副本,所有类的对象共享该变量。静态成员函数则没有 this 指针,可以直接访问静态成员变量

A class must be defined—not just declared—before we can write code that creates objects of that type. Otherwise, the compiler does not know how much storage such objects need.

class ListNode {
private:
    ListNode* next; // recursive structure pointer, size is a pointer size!
    ListNode* prev;
}
```
    class func {
    public:

        func(int a) : a_(a){}

        // 加const之前,this指针是 func* const this
        // 但加之后, this 指针是 const func* const this, 不能修改值
        void display() const {
            cout << this->a_ << endl;
            this->a_ = 50; // error, 但是我们可以将a_变成mutable,这样就可以修改a_
            cout << "we use mutable a_:" << this->a_ << endl;
        }
        private:
            mutable int a_; // mutable 破坏了const的约定
        };

    int main(){
        func func1(10);
        func1.display();

        system("pause");
        return 0;
    }

    10
    we use mutable a_:50
    Press any key to continue . . . 
```

```
    class func {
    public:

        func(int a) : a_(a){}

        func move(int a) {
            this->a_ = a;
            cout << "move:" << this->a_ << endl;
            return *this; // return copy of the class
        }

        func& set(int a) {
            this->a_ = a;
            cout << "set:" << this->a_ << endl;
            return *this; // return an object
        }
        
        int a_;
    };

    int main(){
        func func1(10);
        // why this happened!
        // func temp_func1 = func1.move(20);
        // then temp.func1.set(30);
        // so we cannot set the original a_ to 30, instead we set a temp a_ to 30!

        // modify: (simply return a func&, the address!)
        // func& move(int a) {
        //     this->a_ = a;
        //     cout << "move:" << this->a_ << endl;
        //     return *this; // return copy of the class
        // }
        func1.move(20).set(30);
        cout << "a_:" << func1.a_ << endl;

        system("pause");
        return 0;
    }

move:20
set:30
a_:20
```

7.3.2 常函数和非常函数:

在 C++ 中,可以通过在成员函数的声明中加上 const 关键字来定义常函数和非常函数。常函数指的是该成员函数不会修改对象的数据成员,而非常函数则指的是该成员函数可以修改对象的数据成员。

常函数的声明如下:

    void func() const;

在函数名后面加上 const 关键字即可定义常函数。常函数不能修改对象的数据成员,可以调用对象的其他常函数,但不能调用非常函数。

非常函数的声明如下:

    void func();

非常函数可以修改对象的数据成员,也可以调用对象的常函数和非常函数。需要注意的是,如果对象是 const 类型,则不能调用非常函数

在实现成员函数时,需要根据函数是否被声明为常函数来添加 const 关键字,以确保常函数不会修改对象的数据成员。例如:

    class MyClass {
    public:
    int getValue() const {
        // 常函数不能修改数据成员
        return m_value;
    }

    void setValue(int value) {
        // 非常函数可以修改数据成员
        m_value = value;
    }

    private:
    int m_value;
    };

7.4 Class scope

7.5

  1. assign and initialization:

Constructor Initializer List

class A {
public:
    int a_;
    int b_;
    int c_;

    A(int a, int b, int c) : a_(a), b_(b), c_(c) {} // initialization

    // before assign there is a initialization 
    A(int a, int b, int c) : a_(0), bool(false), int(0) {
        this->a_ = a; // assign
        this->b_ = b;
        this->c_ = c;
    }
    // initialization happened before assign!
    A(int a, int b, int c) {
        this->a_ = a; // assign
        this->b_ = b;
        this->c_ = c;
    }
};

We must use the constructor initializer list to provide values for members that
are const, reference, or of a class type that does not have a default
constructor

class A {
private:
    int d_;
public:
    int a_;
    const int b_;
    int& c_;

    A(int d, int a, int b, int& c) : b_(b), c_(c) {
        this->d_ = d;
        this->a_ = a;
    }
    // const and reference must be initialized! If we assign them within the block, it will be an error!
};

int main(int argc, char** argv){
    int c = 40;
    A a1(10,20,30,c);
    cout << a1.a_ << " " <<a1.b_ << " "<< a1.c_ << endl; // 20 30 40
    return 0;
}

7.5.2. Delegating Constructors

  1. 类里面的成员变量一定要有一个默认构造
    In practice, it is almost always right to provide a default constructor if other
    constructors are being defined

  2. 千万不要隐式转化 explicit func(int a) : a_(a), b_(b), c_© {}

func(int a, int b, int c) : a_(a), b_(b), c_(c) {
    cout << "three args";
}

func(int a, int b) :func(a,b,10) {
    cout << "two args";
}

func(int a): func(a,10,20) {
    cout << "one arg";
}

void callfunc(func func1) {
    cout << "123";
}

int main() {
    func func1(10,20);
    // three args
    // two args
    // initialization prioir to assign

    callfunc(20);
    // one arg
    // 123
    // that's because func(int a) is implicit it can convert callfunc(20) to callfunc(func(20))
    // to solve it, we can add explicite before fun(int a);
    .. explicit func(int a) : func(a,10,20)
}

7.6. static Class Members

this 指针是指向当前对象的指针,可以用于访问对象的成员和调用对象的方法。this 指针是隐式的,在成员函数内部使用,无需显式地定义

static 可以声明在类内,但是必须在内外定义!

class Person {
public:
    static int count;
};
int Person::count = 0;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值