c++封装继承多态

        1.类和对象的一些概念 

class MyClass {
private:
    int myInt;

public:
    void setInt(int value);
    int getInt();
};

myclass是定义的一个类(class),里面有成员变量myint的定义和成员函数setint、getint的声明。

private下的myint只能在类的内部访问,在外部不能访问。下面就是错的

#include<iostream>
using namespace std;
class stu {
private:
	int val;
public:
	void setval(int x);
};
void stu::setval(int x) {
	val = x;
}
int main() {
	stu s;
	s.setval(5) ;
	cout << s.val;
}

不能直接cout private类型的val;修改如下

#include<iostream>
using namespace std;
class stu {
private:
	int val;
public:
	void setval(int x);
	void printval() {
		cout << val;
	}
};
void stu::setval(int x) {
	val = x;
}
int main() {
	stu s;
	s.setval(5) ;
	s.printval();
}

---------------------------------------------------------------------------------------------------------------------------------

void MyClass::setInt() {
    // 成员函数的定义
    // 实现函数的具体操作
}

成员函数的定义(在类的外部), 需要注意的是,成员函数在定义时必须使用类名和作用域解析运算符(::)来标识其归属的类。当然,,也可以在声明时直接定义。

MyClass obj;  // 创建一个 MyClass 类的对象 obj

创建了类的对象。

2.构造函数和析构函数 constructor destructor

一、构造函数

类的成员函数中特殊的一类函数,名字和classname相同,没有返回值,用于在创建对象时进行初始化操作

class MyClass {
private:
    int x;
    int y;

public:
    // 默认构造函数
    MyClass() {
        x = 0;
        y = 0;
    }

    // 带参数的构造函数
    MyClass(int a, int b) {
        x = a;
        y = b;
    }
};

默认构造函数没有参数,将成员变量初始化为设定的值(不一定为0)

注意:默认构造函数后面无括号

MyClass obj1; // 使用默认构造函数创建对象
MyClass obj2(1, 2); // 使用带参数的构造函数创建对象

使用构造函数创建对象。

对加红字体的解释:下面是错的

 MyClass obj1; // 使用默认构造函数创建对象
    cout << obj1.x << obj1.y << endl;
    obj1(1, 2); // 使用带参数的构造函数创建对象
    cout << obj1.x << obj1.y << endl;

二、析构函数

class MyClass {
public:
    MyClass() {
        cout << "Constructor called" << endl;
    }

    ~MyClass() {
        cout << "Destructor called" << endl;
    }
};

函数名称为~classname,暂时没用到。析构函数(Destructor)是一种特殊的成员函数,用于在对象被销毁时执行清理和释放资源的操作

3.成员初始化列表

位于构造函数的定义中,在构造函数的参数列表之后,使用冒号(:)来引导,用于初始化类的成员变量。成员初始化列表(Member Initialization List)是构造函数用于初始化成员变量的一种方式。它允许你在构造函数的定义中直接为成员变量赋初值,而不是在构造函数体内逐个赋值。

class Student {
public:
    // 构造函数声明
    Student(char* name, int age, float score);

public:
    // 公有成员函数声明
    void show();
    char* getname() const;
    int getage() const;
    float getscore() const;

private:
    // 私有成员变量
    char* m_name;
    int m_age;
    float m_score;
};

// 构造函数定义
Student::Student(char* name, int age, float score): m_name(name), m_age(age), m_score(score) { }

以下为成员初始化列表的基本形式

ConstructorName::ConstructorName(parameters) : member1(value1), member2(value2), ... {
    // 构造函数的主体
}

4.this指针

this关键字用于在类的成员函数中区分成员变量和局部变量(或参数)名字相同的情况

class MyClass {
public:
    int x;

    void setX(int x) {
        this->x = x;
    }
};

把成员变量改为val后可删去this,否则不可

5.友元函数

友元函数是在类内部声明的函数,但可以访问类的私有成员和保护成员。要声明一个友元函数,需要在类的内部进行声明,并在函数原型前加上关键字friend。友元函数的声明通常放在类的publicprivateprotected部分中,但它们不属于类的成员函数

class MyClass {
private:
    int x;
public:
    MyClass(int value) : x(value) {}

    friend void friendFunction(MyClass obj); // 友元函数的声明

    void printX() {
        cout << "x = " << x << endl;
    }
};

// 友元函数的定义
void friendFunction(MyClass obj) {
    obj.x += 10; // 可以访问私有成员x
    cout << "Friend function: x = " << obj.x << endl;
}

以下为运行结果

MyClass obj(5);
    obj.printX(); // 输出: x = 5

    friendFunction(obj); // 调用友元函数

    obj.printX(); // 输出: x = 15

友元函数的意义:允许不属于类的成员函数访问private的val

6.静态成员变量和静态成员函数

一、静态成员变量

静态成员变量的共享性体现如下

class Counter {
public:
    static int count; // 静态成员变量,用于计数

    Counter() {
        count++; // 每创建一个Counter对象,count加一
    }
};

int Counter::count = 0; // 静态成员变量的定义和初始化

int main() {
    Counter c1;
    std::cout << "Count: " << Counter::count << std::endl;

    Counter c2;
    std::cout << "Count: " << Counter::count << std::endl;

    Counter c3;
    std::cout << "Count: " << Counter::count << std::endl;

    return 0;
}

用到了构造函数、输出结果为1,2,3;

其中涉及到对静态成员变量初始化的方法:

1.外部

class MyClass {
public:
    static int myStaticInt;
};

int MyClass::myStaticInt = 0; // 初始化静态成员变量

2.常规的内部 错误

class MyClass {
public:
    static int myStaticInt = 0; // 初始化静态成员变量
};

不能用构造函数初始化列表进行对静态成员变量的初始化,解释如下:
构造函数是用于实例化对象的,而静态成员变量属于类本身。这句话的含义解释如下:

构造函数是用于创建类的对象并初始化其成员变量的特殊成员函数,它在对象被实例化时被调用。构造函数负责为对象分配内存,并对对象的成员变量进行初始化。

静态成员变量属于类本身(体现了静态成员变量的共享性),而不是类的每个对象。它们在类级别上存在,不依赖于任何特定的对象实例。静态成员变量与类相关联,而不是与对象相关联

深入静态成员变量的共享性:

静态成员变量在类级别上存在,并且在内存中只有一份拷贝。无论创建多少个对象实例,它们都共享同一个静态成员变量。如果对静态成员变量进行修改,所有的对象都会受到影响。

因此,可以说静态成员变量不属于类的每个对象,而是属于整个类本身。它们提供了一种在不同对象之间共享和访问数据的方式

二、静态成员函数

静态成员函数也是属于类本身,而不是每个类的对象,也是只有一份拷贝。

静态成员函数可以直接通过类名调用,而无需创建类的对象实例。它们只能访问和操作静态成员变量,但不能访问非静态成员变量(非静态成员函数可以访问所有成员变量),因为非静态成员变量依赖于对象实例。静态成员函数通常用于执行与类相关的操作

静态成员函数和非静态成员函数的区别:

  1. 调用方式:成员函数是通过类的对象来调用的,而静态成员函数可以使用类名直接调用,无需创建对象。

    class car{
    public:
        static int totalCount;
        int val;
    public:
        static int getTotalCount() {
        return totalCount; // 静态成员函数返回汽车对象的总数
        }
        int func(){
        return val;
        }
    }
    int main(){
    cout<<car::getTotalCount()<<endl;
    car c;
    cout<<c.func()<<endl;
    

此外,静态成员函数也可以通过对象调用

class MyClass {
public:
  static void staticMemberFunction() {
    std::cout << "Static member function called" << std::endl;
  }
};
int main() {
  MyClass object;
  object.staticMemberFunction(); // 使用对象名调用静态成员函数

  return 0;
}

2.访问权限

成员函数可以访问类的所有成员,包括静态成员变量和非静态成员变量。静态成员函数只能访问静态成员变量和其他静态成员函数,不能访问非静态成员变量和非静态成员函数。

静态成员函数无法直接访问非静态成员,是因为静态成员函数与类关联而不与对象关联。

静态成员函数在编译时期就已经确定,它不依赖于任何具体的对象实例。因此,静态成员函数没有隐含的this指针,也就无法通过this指针来访问非静态成员变量或非静态成员函数。

3.存储方式

成员函数存储在对象中,每个对象都有一份成员函数的拷贝。静态成员函数不属于任何对象,它们与类相关联,只有一份拷贝。

4.

生命周期:成员函数的生命周期与对象的生命周期相同。静态成员函数的生命周期与程序运行的整个过程相同,它们在程序开始执行时创建,在程序结束时销毁。

7.const成员变量和const成员函数以及“const对象”

class MyClass {
public:
    int value;

    void setValue(int newValue) {
        value = newValue;
    }
};

int main() {
    const MyClass obj;  // 声明一个 const 对象 obj

    // obj.value = 10;  // 错误,不能修改 const 对象的成员变量的值
    // obj.setValue(10);  // 错误,不能调用非 const 成员函数

    return 0;
}

以上为const对象,const对象不能调用非const成员函数、非const随便

const成员函数的基本形式:datatype func_name(peremetres) const;

const写在函数尾部

比如:char *getname() const;

const成员变量和const成员函数的关系(暂时未知,好像不太重要的样子)

一般把获取对象的属性 函数声明为const

比如

int getValue() const {
        return value;
    }

const成员变量一旦初始化任何时候不能被修改,const成员函数可以访问const变量和非const变量,它的特点是不能修改成员变量的值,无论是const 非const。const对象只能访问const成员变量和const成员函数

8.继承和派生

类与类的关系

继承就是一个类包含一个类。通过继承,派生类可以获得基类的属性和方法,并且可以在派生类中添加新的属性和方法,扩展基类的功能。换句话说,派生类是基类的特化或扩展。

代码展示如下

// 基类 Animal
class Animal {
public:
    void eat() {
        cout << "Animal is eating." << endl;
    }
};

// 派生类 Dog
class Dog : public Animal {
public:
    void bark() {
        cout << "Dog is barking." << endl;
    }
};

int main() {
    Dog dog;
    dog.eat();  // 继承自基类 Animal 的 eat() 方法
    dog.bark(); // Dog 类独有的 bark() 方法

    return 0;
}

继承的语法:class derived_name public(private)【继承的方式】     base_name{}

继承的方式:public、private、protected

继承的访问权限

 
#include<iostream>
using namespace std;
// 基类 Base
class Base {
public:
    int publicMember;
protected:
    int protectedMember;
private:
    int privateMember;
};
// 公有继承
class PublicDerived : public Base {
public:
    void accessBaseMembers() {
        publicMember = 1;      // 可以直接访问公有成员
        protectedMember = 2;   // 可以直接访问保护成员
        //privateMember = 3;     // 无法直接访问私有成员
    }
};
 
// 私有继承
class PrivateDerived : private Base {
public:
    void accessBaseMembers() {
         publicMember = 1;      // 无法直接访问公有成员
         protectedMember = 2;   // 无法直接访问保护成员
       //privateMember = 3;     // 无法直接访问私有成员
    }
};
 
// 保护继承
class ProtectedDerived : protected Base {
public:
    void accessBaseMembers() {
         publicMember = 1;      // 无法直接访问公有成员
         protectedMember = 2;   // 无法直接访问保护成员
       //privateMember = 3;     // 无法直接访问私有成员
    }
};
int main() {
    
    PublicDerived obj1;
    obj1.accessBaseMembers();
    cout << obj1.publicMember << endl;
    /*cout << obj1.privateMember << endl;
    cout << obj1.protectedMember << endl;
    */
    PrivateDerived obj2;
    obj2.accessBaseMembers();
    /*cout << obj2.publicMember << endl;
    cout << obj2.privateMember << endl;
    cout << obj2.protectedMember << endl;*/
    ProtectedDerived obj3;
    obj3.accessBaseMembers();
   /* cout << obj3.publicMember << endl;
    cout << obj3.privateMember << endl;
    cout << obj3.protectedMember << endl*/
        
}
 

在public继承类中可以访问public、protected成员,在main函数中(继承类外部)只能访问public成员

在protected、private的继承类中可以访问public、protected成员,在main函数中都不能访问

类成员的访问权限由高到低依次为 public --> protected --> private

下表汇总了不同继承方式对不同属性的成员的影响结果

继承方式/基类成员 public成员 protected成员 private成员 public继承 public protected 不可见 protected继承 protected protected 不可见 private继承 private private 不可见

上表为基类成员在派生类中的访问权限

在派生类中访问基类 private 成员的唯一方法就是借助基类的非 private 成员函数,如果基类没有非 private 成员函数,那么该成员在派生类中将无法访问。

改变访问权限

using关键字改变、还没弄清

留白

继承时会有名字相同的问题,成员变量和成员函数,若无域解析符::时会屏蔽base-class的 变量

如下

class Base {
public:
    int x;
    void display() {
        cout << "Base: " << x << endl;
    }
};

// 派生类Derived
class Derived : public Base {
public:
    int x;  // 与基类中的成员变量同名

    void display() {
        cout << "Derived: " << x << endl;
    }

    void displayBase() {
        cout << "Base in Derived: " << Base::x << endl;
        Base::display();  // 通过作用域解析运算符访问基类的成员函数
    }
};

int main() {
    Derived d;
    d.x = 10;         // 设置派生类中的成员变量x
    d.Base::x = 20;   // 设置基类中的成员变量x
    d.display();      // 调用派生类中的display()
    d.Base::display();  // 通过作用域解析运算符调用基类中的display()
    d.displayBase();  // 调用派生类中的displayBase(),同时访问基类的成员变量和成员函数
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值