#include<string>#include<string_view>classPerson{private:std::stringm_name;intm_age{};public:Person(std::string_viewname,intage):m_name{name},m_age{age}{}conststd::string&getName()const{returnm_name;}intgetAge()const{returnm_age;}};classEmployee{private:std::stringm_employer;doublem_wage{};public:Employee(std::string_viewemployer,doublewage):m_employer{employer},m_wage{wage}{}conststd::string&getEmployer()const{returnm_employer;}doublegetWage()const{returnm_wage;}};// Teacher publicly inherits Person and EmployeeclassTeacher:publicPerson,publicEmployee{private:intm_teachesGrade{};public:Teacher(std::string_viewname,intage,std::string_viewemployer,doublewage,intteachesGrade):Person{name,age},Employee{employer,wage},m_teachesGrade{teachesGrade}{}};intmain(){Teachert{"Mary",45,"Boo",14.3,8};return0;}
// h/t to reader Waldo for this example#include<string>structPoint2D{intx;inty;};classBox// mixin Box class{public:voidsetTopLeft(Point2Dpoint){m_topLeft=point;}voidsetBottomRight(Point2Dpoint){m_bottomRight=point;}private:Point2Dm_topLeft{};Point2Dm_bottomRight{};};classLabel// mixin Label class{public:voidsetText(conststd::string_viewstr){m_text=str;}voidsetFontSize(intfontSize){m_fontSize=fontSize;}private:std::stringm_text{};intm_fontSize{};};classButton:publicBox,publicLabel{};intmain(){Buttonbutton{};button.Box::setTopLeft({1,1});button.Box::setBottomRight({10,10});button.Label::setText("Username: ");button.Label::setFontSize(6);}
// The Curiously Recurring Template Pattern (CRTP)template<classT>classMixin{// Mixin<T> can use template type parameter T to access members of Derived// via (static_cast<T*>(this))};classDerived:publicMixin<Derived>{};
#include<iostream>classUSBDevice{private:longm_id{};public:USBDevice(longid):m_id{id}{}longgetID()const{returnm_id;}};classNetworkDevice{private:longm_id{};public:NetworkDevice(longid):m_id{id}{}longgetID()const{returnm_id;}};classWirelessAdapter:publicUSBDevice,publicNetworkDevice{public:WirelessAdapter(longusbId,longnetworkId):USBDevice{usbId},NetworkDevice{networkId}{}};intmain(){WirelessAdapterc54G{5442,181742};std::cout<<c54G.getID();// Which getID() do we call?return0;}
在这种情况下会出现许多问题:例如,复印机中是否应该有两份PoweredDevice,以及如何解决某些类型的模糊引用。虽然这些问题中的大多数都可以通过显式作用域来解决,但为了处理增加的复杂性而向类添加的维护开销可能会导致开发时间急剧增加。我们将在下一章中讨论更多解决菱形继承问题的方法(18.8 -- Virtual base classes)。