C++学习路线(二十七)

虚基类

菱形继承的重大缺点

cpp 复制代码
#include <iostream>
using namespace std;

class Tel { // 电话类
public:
	Tel() {
		this->number = 0;
	}
protected:
	int number;
};

class FixLine : public Tel { // 固定电话类
};

class MobilePhone : public Tel { // 移动电话类
};
//无线座机
class WirelessLine : public MobilePhone, public FixLine{ // 无线电话类
public:
	void setNumber(int num) {
		this->Tel::number = num;
	}
	int getNumber() {
		return this->Tel::number;
	}


};
int main() {

	return 0;
}

比如说FixLine,继承于Tel MobilePhone也继承于Tel 那么如果调用number 就会报错

这种情况可以使用虚继承和虚基类进行解决。

cpp 复制代码
#include <iostream>
using namespace std;

class Tel { // 电话类
public:
	Tel() {
		this->number = 0;
	}
protected:
	int number;
};

class FixLine : virtual public Tel { // 固定电话类

};

class MobilePhone : virtual public Tel { // 移动电话类

};
//无线座机
class WirelessLine : public MobilePhone, public FixLine{ // 无线电话类
public:
	void setNumber(int num) {
		this->number = num;
	}
	int getNumber() {
		return this->number;
	}


};
int main() {

	return 0;
}

之前的相亲项目的改造

对Girl类和Boy类进行重构:

  1. 抽取出共同的方法和数据成员, 用来构建一个新的基类[父类]
  2. Girl和Boy类修改为从Human类继承,并修改相关代码。

Human.h

#pragma once
#include <string>
class Humans {
public:
    Humans(std::string name, int age) :   name(name), age(age) {}
    int getAge() const;
    std::string getName() const;
    std::string Description() const;
private:
    std::string name;
    int age;
};

Human.cpp

#include "Human.h"
#include "sstream"
Humans::Humans(std::string name, int age)
{
    this->name = name;
    this->age = age;
}
int Humans::getAge() const {
    return age;
}
std::string Humans::getName() const {
    return name;
}
std::string Humans::Description() const {
    std::stringstream ss;
    ss << "Name: " << name << ", Age: " << age;
    return ss.str();
}

boy.h

#pragma once
#include <string>
#include <vector>
#include "../继承/Human.h"
class Girl;

class Boy : public Humans {
public:
	Boy(std::string name, int age, int salary);
	std::string Description() const;
	int getSalary() const;
	bool satisfy(const Girl& other);
	static void inputsBoys(std::vector<Boy>& boys);
private:
	int salary;
};

boy.cpp

#include <sstream>
#include <string>
#include "boy.h"
#include "girl.h"

#define SALARY_FACTOR 0.005

Boy::Boy(std::string name, int age, int salary) : Humans(name, age) , salary(salary) {}
int Boy::getSalary() const {
    return salary;
}
std::string Boy::Description() const {
    std::stringstream ss;
    ss << getName() << "工资" << salary << " 年龄" << getAge();
    return ss.str();
}
void Boy::inputsBoys(std::vector<Boy>& boys) {
    int n = 1;
    std::string name;
    int age;
    int salary;
    while (1) {
        std::cout << "请输入第" << n << "位男孩的信息(输入0结束输入):" << std::endl;
        std::cout << "年龄:" << std::endl;
        std::cin >> age;
        if (age == 0) break;
        std::cout << "姓名:" << std::endl;
        std::cin >> name;
        std::cout << "工资:" << std::endl;
        std::cin >> salary;
        boys.push_back(Boy(name, age, salary));
        n++;
    }
}

bool Boy::satisfy(const Girl& girl) {
    if (girl.getBeauty() >= salary * SALARY_FACTOR) {
        return true;
    }
    else return false;
}

girl.h

#pragma once
#include <iostream>
#include <string>
#include <vector>
#include "../继承/Human.h"
class Boy;

class Girl : public Humans {
public:
	Girl(std::string name, int age, int beauty);
	std::string Description() const;
	int getBeauty() const;
	bool satisfy(const Boy& boy) const;
	static void inputsGirls(std::vector<Girl>& girls);
private:
	int beauty;
};

girl.cpp

#include "girl.h"
#include "boy.h"
#include <string>
#include <sstream>

#define YANZHI_FACTOR 1.1

Girl::Girl(std::string name, int age, int beauty) : Humans(name, age), beauty(beauty) {}
int Girl::getBeauty() const {
    return beauty;
}
std::string Girl::Description() const {
    std::stringstream ss;
    ss << getName() << "颜值" << beauty << " 年龄" << getAge();
    return ss.str();
}
bool Girl::satisfy(const Boy& boy) const {
    if(boy.getSalary() >= beauty * YANZHI_FACTOR) return true;
    return false;
}
void Girl::inputsGirls(std::vector<Girl>& girls) {
    int age;
    std::string name;
    int beauty;
    int n = 1;
    while (1) {
        std::cout << "请输入第" << n << "位女孩的信息(输入0结束输入):" << std::endl;
        std::cout << "年龄:" << std::endl;
        std::cin >> age;
        if (age == 0) break;
        std::cout << "姓名:" << std::endl;
        std::cin >> name;
        std::cout << "颜值:" << std::endl;
        std::cin >> beauty;
        n++;
        girls.push_back(Girl(name, age, beauty));
    }
}

main.cpp不变

常见错误总结

默认访问权限和语法要求

默认访问权限是private

访问权限之后一定要加冒号:

指定为某种访问权限之后, 就一直是这种权限, 除非再次指定为其他权限.

cpp 复制代码
class MyClass{
    void func(); // private
}

类的成员的访问权限, 与继承方式的区别

相同点:都有public, private, protected

不同点:意义完全不同。

小结:

成员的访问权限:

public, 可以通过外部来访问(通过对象直接访问), 类似于C语言结构体中的成员

private, 只能在内部访问(在这个类的成员函数内访问),但是在子类的内部不能直接访问。

protected, 只能在内部访问,而且可以在子类的内部直接访问。

继承方式:

public, 父类成员, 被继承到子类后,访问权限都不变。

private, 父类成员, 被继承到子类后,访问权限都变为private

protected, 父类成员, 被继承到子类后,public权限的成员,降级为protected, 其他不变。

项目扩展-位图算法

问题:

有很多不重复的整数, 其中最大值不超过40亿, 最小值是0.

要求判断某个指定的整数, 是否在这个集合中.

cpp 复制代码
#include <iostream>
using namespace std;

void init(char* data, int len) {
	unsigned int n = len * 8;
	for (int i = 0; i < n; i++) {
		if (i % 3 == 0) {
			cout << i << " ";
			char* p = data + i / 8;
			*p |= (1 << (i % 8));
		}
	}
	cout << endl;
}

bool check(char* data, int value) {
	char* p = data + value / 8;
	bool ret =  *p & (1 << (value % 8));
	return ret;
}

int main() {
	unsigned int n = 400;
	int len = n / 8 + 1;
	char* data = (char*)malloc(len);
	memset(data, 0, len);
	init(data, len);
	while (1) {
		int value;
		cin >> value;
		if (value == -1) break;
		if (check(data, value)) cout << "1" << endl;
		else cout << "0" << endl;
	}
	free(data);
	return 0;
}

项目练习一-练习一

定义一个类Book, 用来描述新书, 具有以下功能:
查看当前价格.

查看当前的书号

定义一个类SellBook, 用来表示促销的书籍, 要求继承自Book

具有以下功能:

  1. 查看当前折扣
  2. 设置当前折扣
  3. 查看当前的促销价

Book.h

cpp 复制代码
#pragma once
#include <iostream>
#include <string>
class Book {
public:
	Book(float price, std::string isbn);
	~Book();
	float getPrice() const;
	std::string getISBN() const;
protected:
	double price;
	std::string isbn;
};

Book.cpp

cpp 复制代码
#include "Book.h"

Book::Book(float price, std::string isbn) {
    this->price = price;
    this->isbn = isbn;
}

Book::~Book() {

}

float Book::getPrice() const {
    return price;
}
std::string Book::getISBN() const {
    return isbn;
}

SellBook.h

cpp 复制代码
#pragma once
#include "Book.h"
class SellBook : public Book {
public:
	SellBook(float price, std::string isbn, float discount);
	~SellBook();
	float getPrice() const;
	float getDiscount() const;
private:
	float discount;
};

SellBook.cpp

cpp 复制代码
#include "SellBook.h"

SellBook::SellBook(float price, std::string isbn , float discount) : Book(price, isbn), discount(discount){}
SellBook::~SellBook(){}

float SellBook::getPrice() const {
	return price * discount / 10.0;
}
float SellBook::getDiscount() const {
	return discount;
}

main.cpp

cpp 复制代码
#include <iostream>
#include "Book.h"
#include "SellBook.h"
using namespace std;

int main()
{
    Book b1(30, "123-123");
    SellBook sb1(30, "456-456", 5);
    cout << "Book price: " << b1.getPrice() << endl;
    cout << "SellBook price: " << sb1.getPrice() << endl;

    return 0;
}
相关推荐
程序猿阿伟6 分钟前
《C++中的魔法:实现类似 Python 的装饰器模式》
java·c++·装饰器模式
zyhomepage8 分钟前
科技的成就(六十四)
开发语言·人工智能·科技·算法·内容运营
Ethan Wilson14 分钟前
C++/QT可用的websocket库
开发语言·c++·websocket
想做白天梦26 分钟前
多级反馈队列
java·windows·算法
潇雷28 分钟前
算法Day12|226-翻转二叉树;101-对称二叉树;104-二叉树最大深度;111-二叉树最小深度
java·算法·leetcode
爱编程— 的小李1 小时前
开关灯问题(c语言)
c语言·算法·1024程序员节
韭菜盖饭1 小时前
LeetCode每日一题3211---生成不含相邻零的二进制字符串
数据结构·算法·leetcode
糊涂君-Q1 小时前
Python小白学习教程从入门到入坑------第十九课 异常模块与包【下】(语法基础)
开发语言·python·学习·程序人生·改行学it
ergevv1 小时前
类的变量的初始化:成员初始化列表、就地初始化
c++·初始化·
爱编程的小新☆1 小时前
Java篇图书管理系统
java·开发语言·学习