C++学习路线(二十七)
虚基类
菱形继承的重大缺点
#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 就会报错
这种情况可以使用虚继承和虚基类进行解决。
#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类进行重构:
- 抽取出共同的方法和数据成员, 用来构建一个新的基类[父类]
- 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
访问权限之后一定要加冒号:
指定为某种访问权限之后, 就一直是这种权限, 除非再次指定为其他权限.
class MyClass{
void func(); // private
}
类的成员的访问权限, 与继承方式的区别
相同点:都有public, private, protected
不同点:意义完全不同。
小结:
成员的访问权限:
public, 可以通过外部来访问(通过对象直接访问), 类似于C语言结构体中的成员
private, 只能在内部访问(在这个类的成员函数内访问),但是在子类的内部不能直接访问。
protected, 只能在内部访问,而且可以在子类的内部直接访问。
继承方式:
public, 父类成员, 被继承到子类后,访问权限都不变。
private, 父类成员, 被继承到子类后,访问权限都变为private
protected, 父类成员, 被继承到子类后,public权限的成员,降级为protected, 其他不变。
项目扩展-位图算法
问题:
有很多不重复的整数, 其中最大值不超过40亿, 最小值是0.
要求判断某个指定的整数, 是否在这个集合中.
#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类
具有以下功能:
- 查看当前折扣
- 设置当前折扣
- 查看当前的促销价格
Book.h
#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
#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
#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
#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
#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;
}