首页 > 编程语言 >07c/c++面向对象

07c/c++面向对象

时间:2024-06-07 23:32:47浏览次数:17  
标签:cout 继承 void c++ 面向对象 int 07c 父类 public

07C/c++零碎语法

目录

文章目录

C

1.封装

#include <stdio.h>

// 定义一个结构体,封装学生的信息
typedef struct {
    int id;       // 学生ID
    char name[50]; // 学生姓名
    float score;   // 学生成绩
} Student;

// 定义一个函数,用于设置学生的信息
void setStudentInfo(Student *s, int id, const char *name, float score) {
    s->id = id;
    strncpy(s->name, name, sizeof(s->name) - 1);
    s->name[sizeof(s->name) - 1] = '\0'; // 确保字符串以空字符结尾
    s->score = score;
}

// 定义一个函数,用于打印学生的信息
void printStudentInfo(const Student *s) {
    printf("Student ID: %d\n", s->id);
    printf("Student Name: %s\n", s->name);
    printf("Student Score: %.2f\n", s->score);
}

int main() {
    // 创建一个学生实例
    Student stu;
    
    // 设置学生信息
    setStudentInfo(&stu, 1, "John Doe", 92.5);
    
    // 打印学生信息
    printStudentInfo(&stu);
    
    return 0;
}

2.继承

#include <stdio.h>

// 定义一个父类结构体
typedef struct {
    int id;
    char name[50];
} Animal;

// 定义一个子类结构体,嵌入父类结构体
typedef struct {
    Animal base; // 父类属性
    float weight;
} Cat;

// 定义一个函数,用于设置Animal的基本信息
void setAnimalInfo(Animal *a, int id, const char *name) {
    a->id = id;
    strncpy(a->name, name, sizeof(a->name) - 1);
    a->name[sizeof(a->name) - 1] = '\0';
}

// 定义一个函数,用于打印Animal的信息
void printAnimalInfo(const Animal *a) {
    printf("Animal ID: %d\n", a->id);
    printf("Animal Name: %s\n", a->name);
}

// 定义一个函数,用于设置Cat的详细信息
void setCatInfo(Cat *c, int id, const char *name, float weight) {
    setAnimalInfo(&c->base, id, name); // 继承父类的方法
    c->weight = weight;
}

// 定义一个函数,用于打印Cat的信息
void printCatInfo(const Cat *c) {
    printAnimalInfo(&c->base); // 继承父类的方法
    printf("Cat Weight: %.2f\n", c->weight);
}

int main() {
    Cat myCat;
    setCatInfo(&myCat, 1, "Whiskers", 4.5);
    printCatInfo(&myCat);
    
    return 0;
}

3.多态

#include <stdio.h>

// 定义一个基类结构体
typedef struct {
    void (*print)(void*); // 函数指针,用于多态
} Animal;

// 定义一个派生类结构体
typedef struct {
    Animal base;
    int age;
} Dog;

// 基类的print函数
void animalPrint(void *self) {
    printf("I'm an animal.\n");
}

// 派生类的print函数
void dogPrint(void *self) {
    Dog *dog = self;
    printf("I'm a dog and I'm %d years old.\n", dog->age);
}

int main() {
    Animal animal;
    Dog dog;

    // 初始化基类
    animal.print = animalPrint;

    // 初始化派生类
    dog.base.print = dogPrint;
    dog.age = 5;

    // 多态调用
    animal.print(&animal);
    dog.base.print(&dog);

    return 0;
}

C++

4.1 封装

4.1.1 封装的意义

封装意义:一

**示例1:**设计一个圆类,求圆的周长

示例代码:

//圆周率
const double PI = 3.14;

//封装一个圆类,求圆的周长
//class代表设计一个类,后面跟着的是类名
class Circle
{
public:  //访问权限  公共的权限

	//属性
	int m_r;//半径

	//行为
	//获取到圆的周长
	double calculateZC()
	{
		//2 * pi  * r
		//获取圆的周长
		return  2 * PI * m_r;
	}
};

int main() {

	//通过圆类,创建圆的对象
	Circle c1;
	c1.m_r = 10; //给圆对象的半径 进行赋值操作

	//2 * pi * 10 = = 62.8
	cout << "圆的周长为: " << c1.calculateZC() << endl;
	system("pause");
	return 0;
}

封装意义二:

类在设计时,可以把属性和行为放在不同的权限下,加以控制

示例:

//三种权限
//公共权限  public     类内可以访问  类外可以访问
//保护权限  protected  类内可以访问  类外不可以访问  儿子可以访问父亲中的保护内容
//私有权限  private    类内可以访问  类外不可以访问	儿子不可以访问父亲中的私有内容

class Person
{
	//姓名  公共权限
public:
	string m_Name;

	//汽车  保护权限
protected:
	string m_Car;

	//银行卡密码  私有权限
private:
	int m_Password;

public:
	void func()
	{
		m_Name = "张三";
		m_Car = "拖拉机";
		m_Password = 123456;
	}
};

int main() {

	Person p;
	p.m_Name = "李四";
	//p.m_Car = "奔驰";  //保护权限类外访问不到
	//p.m_Password = 123; //私有权限类外访问不到

	system("pause");

	return 0;
}

5. 继承

继承

5.1 继承的基本语法

例如我们看到很多网站中,都有公共的头部,公共的底部,甚至公共的左侧列表,只有中心内容不同

接下来我们分别利用普通写法和继承的写法来实现网页中的内容,看一下继承存在的意义以及好处

普通实现:

//Java页面
class Java 
{
public:
	void header()
	{
		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "JAVA学科视频" << endl;
	}
};
//Python页面
class Python
{
public:
	void header()
	{
		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "Python学科视频" << endl;
	}
};
//C++页面
class CPP 
{
public:
	void header()
	{
		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
	}
	void footer()
	{
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分类列表)" << endl;
	}
	void content()
	{
		cout << "C++学科视频" << endl;
	}
};

void test01()
{
	//Java页面
	cout << "Java下载视频页面如下: " << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
	cout << "--------------------" << endl;

	//Python页面
	cout << "Python下载视频页面如下: " << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
	cout << "--------------------" << endl;

	//C++页面
	cout << "C++下载视频页面如下: " << endl;
	CPP cp;
	cp.header();
	cp.footer();
	cp.left();
	cp.content();

}

int main() {

	test01();

	system("pause");

	return 0;
}

继承实现:

//公共页面
class BasePage
{
public:
	void header()
	{
		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
	}

	void footer()
	{
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Java,Python,C++...(公共分类列表)" << endl;
	}

};

//Java页面
class Java : public BasePage
{
public:
	void content()
	{
		cout << "JAVA学科视频" << endl;
	}
};
//Python页面
class Python : public BasePage
{
public:
	void content()
	{
		cout << "Python学科视频" << endl;
	}
};
//C++页面
class CPP : public BasePage
{
public:
	void content()
	{
		cout << "C++学科视频" << endl;
	}
};

void test01()
{
	//Java页面
	cout << "Java下载视频页面如下: " << endl;
	Java ja;
	ja.header();
	ja.footer();
	ja.left();
	ja.content();
	cout << "--------------------" << endl;

	//Python页面
	cout << "Python下载视频页面如下: " << endl;
	Python py;
	py.header();
	py.footer();
	py.left();
	py.content();
	cout << "--------------------" << endl;

	//C++页面
	cout << "C++下载视频页面如下: " << endl;
	CPP cp;
	cp.header();
	cp.footer();
	cp.left();
	cp.content();


}

int main() {

	test01();

	system("pause");

	return 0;
}

总结:

继承的好处:可以减少重复的代码

5.2 继承方式

继承的语法:class 子类 : 继承方式 父类

继承方式一共有三种:

  • 公共继承
  • 保护继承
  • 私有继承

示例:

class Base1
{
public: 
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

//公共继承
class Son1 :public Base1
{
public:
	void func()
	{
		m_A; //可访问 public权限
		m_B; //可访问 protected权限
		//m_C; //不可访问
	}
};

void myClass()
{
	Son1 s1;
	s1.m_A; //其他类只能访问到公共权限
}

//保护继承
class Base2
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son2:protected Base2
{
public:
	void func()
	{
		m_A; //可访问 protected权限
		m_B; //可访问 protected权限
		//m_C; //不可访问
	}
};
void myClass2()
{
	Son2 s;
	//s.m_A; //不可访问
}

//私有继承
class Base3
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};
class Son3:private Base3
{
public:
	void func()
	{
		m_A; //可访问 private权限
		m_B; //可访问 private权限
		//m_C; //不可访问
	}
};
class GrandSon3 :public Son3
{
public:
	void func()
	{
		//Son3是私有继承,所以继承Son3的属性在GrandSon3中都无法访问到
		//m_A;
		//m_B;
		//m_C;
	}
};

5.3 继承中的对象模型

**问题:**从父类继承过来的成员,哪些属于子类对象中?

示例:

class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C; //私有成员只是被隐藏了,但是还是会继承下去
};

//公共继承
class Son :public Base
{
public:
	int m_D;
};

void test01()
{
	cout << "sizeof Son = " << sizeof(Son) << endl;
}

int main() {

	test01();

	system("pause");

	return 0;
}

结论: 父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到

5.4 继承中构造和析构顺序

子类继承父类后,当创建子类对象,也会调用父类的构造函数

问题:父类和子类的构造和析构顺序是谁先谁后?

总结:继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反

5.5 继承同名成员处理方式

问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域

示例:

class Base {
public:
	Base()
	{
		m_A = 100;
	}

	void func()
	{
		cout << "Base - func()调用" << endl;
	}

	void func(int a)
	{
		cout << "Base - func(int a)调用" << endl;
	}

public:
	int m_A;
};


class Son : public Base {
public:
	Son()
	{
		m_A = 200;
	}

	//当子类与父类拥有同名的成员函数,子类会隐藏父类中所有版本的同名成员函数
	//如果想访问父类中被隐藏的同名成员函数,需要加父类的作用域
	void func()
	{
		cout << "Son - func()调用" << endl;
	}
public:
	int m_A;
};

void test01()
{
	Son s;

	cout << "Son下的m_A = " << s.m_A << endl;
	cout << "Base下的m_A = " << s.Base::m_A << endl;

	s.func();
	s.Base::func();
	s.Base::func(10);

}
int main() {

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

总结:

  1. 子类对象可以直接访问到子类中同名成员
  2. 子类对象加作用域可以访问到父类同名成员
  3. 当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

5.6 继承同名静态成员处理方式

问题:继承中同名的静态成员在子类对象上如何进行访问?
静态成员和非静态成员出现同名,处理方式一致

  • 访问子类同名成员 直接访问即可
  • 访问父类同名成员 需要加作用域

总结:同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象 和 通过类名)

5.7 菱形继承

菱形继承概念:

​ 两个派生类继承同一个基类

​ 又有某个类同时继承者两个派生类

​ 这种继承被称为菱形继承,或者钻石继承

菱形继承问题:

  1. 羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。

  2. 草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

示例:

class Animal
{
public:
	int m_Age;
};

//继承前加virtual关键字后,变为虚继承
//此时公共的父类Animal称为虚基类
class Sheep : virtual public Animal {};
class Tuo   : virtual public Animal {};
class SheepTuo : public Sheep, public Tuo {};

void test01()
{
	SheepTuo st;
	st.Sheep::m_Age = 100;
	st.Tuo::m_Age = 200;

	cout << "st.Sheep::m_Age = " << st.Sheep::m_Age << endl;
	cout << "st.Tuo::m_Age = " <<  st.Tuo::m_Age << endl;
	cout << "st.m_Age = " << st.m_Age << endl;
}


int main() {

	test01();

	system("pause");

	return 0;
}

总结:

  • //继承前加virtual关键字后,变为虚继承
    //此时公共的父类Animal称为虚基类
    class Sheep : virtual public Animal {};
  • 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
  • 利用虚继承可以解决菱形继承问题

[续多态]https://editor.csdn.net/md?not_checkout=1&spm=1015.2103.3001.8066&articleId=139442528

标签:cout,继承,void,c++,面向对象,int,07c,父类,public
From: https://blog.csdn.net/2302_79752447/article/details/139411474

相关文章

  • 07C回调函数
    C零碎语法目录文章目录C零碎语法流程1.声明一个函数指针2.定义回调函数3.注册回调函数应用4.事件回调5.同步回调函数6.异步回调函数流程1.声明一个函数指针uint8_t(*p_CallbackFunc)(void);2.定义回调函数重要的是要注意回调函数只是一个函数。由于它的使......
  • c++类与对象
    classBook{public:charname;intpages;voidprintpages();}voidprintpages(){std::cout<<"书的页数"<<endl;}在定义类的属性和方法时可以选择1.public:公有成员(在程序中类的外部是可访问的)。2.protected:受保护成员(在类的外部是不可访问的,甚......
  • c++的面对对象 的 虚函数
    #include<iostream>#include<string>classAnimal{public:virtualvoidmakeSound()=0;//纯虚函数,所有的动物都应该提供自己的叫声};classDog:publicAnimal{public:voidmakeSound()override{std::cout<<"Woof!"<&l......
  • 【C++修行之道】类和对象(五)日期类的实现、const成员、取地址及const和取地址操作符重
    目录一、日期类的实现Date.h 1.1GetMonthDay函数(获取某年某月的天数) 问:这个函数为什么不和其他的函数一样放在Date.cpp文件中实现呢?1.2CheckDate函数(检查日期有效性)、Print函数(打印日期)1.3实现日期类的逻辑运算符重载<运算符的重载 ==运算符重载其他运算符重载......
  • C++AB类相互包含
    本文讨论我们该如何实现如下结构,而不会报错:classA{Bb;}classB{Aa;}我们知道编译器的执行顺序是从上到下的,当我们在A中使用B时,B还没有定义,甚至没有声明,所以在这里我们先给代码加上一段前向声明。classB;classA{Bb;}前向声明让编译器知道B类是......
  • 一篇文章带你搞懂C++引用(建议收藏)
    引用6.1引用概念引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"typedef是给类型取别名引用是给变量取别名注意:引用类型必须和引用实体是同种类......
  • 最大公约数(gcd())和最小公倍数(lcm())的c语言和c++详细解法
    最大公约数(gcd())和最小公倍数(lcm())最大公约数:定义:两个或多个整数共有的约数中最大的一个。例如:整数12和18,他们的公约数有1、2、3、6,其中最大的公约数是6。c语言解法:辗转相除法和更相减损法1、辗转相除法:思路:先求解较大的数除以较小的数的余数,再用较小的数除以前......
  • C++STL---list模拟实现
    本文我们模拟实现STL中的list,为了模拟实现list,实际上我们需要实现三个类,分别为:_list_node,_list_iterator,list。我们先看一下这三个类的基本组成,主要是看看每个类中包含的变量有什么:namespaceCYF{ //模拟实现list当中的结点类 template<classT> struct_list_node......
  • Mat的lambda方式像素高效遍历(C++11)
    Mat的lambda方式像素高效遍历(C++11)文章目录Mat的lambda方式像素高效遍历(C++11)前言一、Mat的lambda方式像素高效遍历二、代码实现总结前言图像遍历是图像处理中的经典操作,快速高效的进行像素遍历对性能的提升至关重要。一、Mat的lambda方式像素高效遍历OpenCV4......
  • 【c++基础】八数码难题
    说明在 3×3 的棋盘上,摆有八个棋子,每个棋子上标有 1 至 8 的某一数字。棋盘中留有一个空格,空格用 0 来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现......