我想在繼承重復時導致錯誤。這是我找到它的方法。
#include <utility>
class Person {};
class Man : public Person {};
class Woman : public Person {};
template <typename... Types>
class merge_class : public Types... {};
template <typename... Types>
struct condition
{
using merge = merge_class<Types...>;
using type = std::enable_if<
std::is_convertible<merge, Person>::value // condition
, merge>::type;
};
class BummooKim : public condition<Man>::type {};
class Daniel : public condition<Woman>::type {};
//class Unkown : public condition<Man, Woman>::type {}; // There is an error in the declaration.
但是,我發現如果存在非默認建構式,則無法使用這種方式。
我想知道是否有一個關鍵字來表明它必須是單繼承的。
如果 c 不支持“關鍵字”,我想要另一種方式。
例子
class OtherWay : public condition<Man, Other>::type
{
OtherWay() : Man() {}
};
uj5u.com熱心網友回復:
您遇到的情況稱為鉆石繼承(https://www.makeuseof.com/what-is-diamond-problem-in-cpp/),除了“介面”外,最好避免 IMO。我更喜歡使用組合實作,也稱為 mixin 模式(反過來使用 CRTP,奇怪的遞回模板模式)。在此模式中,您可以實作單獨的功能(例如,在以下示例中,男人可以大喊大叫,女人可以微笑,所有人都可以打招呼。)。
在編譯時檢測多重繼承是不可能的(C 中可能啟用它的功能從未通過標準委員會)。
我展示了一種至少在編譯時檢測到一個人不能同時是一個男人和一個女人的方法(至少在這個例子中)。
在 MSVC 中,此程式將給出以下編譯錯誤:
Error C2338 Being both a Man and a Woman, is not correct in this program
#include <iostream>
#include <string>
//-----------------------------------------------------------------------------
// multiple inheritance from interfaces (abstract base classes is fine)
// class to introduce a concept of an interface
// and set all the constructors/destructors default behavior.
class Interface
{
public:
virtual ~Interface() = default;
protected:
Interface() = default; // protected constructor, avoids accidental instantiation
};
//-----------------------------------------------------------------------------
// for each aspect/capability of a person define a seperate interface
// this will also allow client code to cast an object to either of those
// interfaces to check if functionality is available
class PersonItf :
public Interface
{
public:
virtual void SayHi() const = 0;
};
//-----------------------------------------------------------------------------
// A man can shout
class ManItf :
public Interface
{
public:
virtual void Shout() const = 0;
};
//-----------------------------------------------------------------------------
// A woman can smile
class WomanItf :
public Interface
{
public:
virtual void Smile() const = 0;
};
//-----------------------------------------------------------------------------
// mixin classes for reusable code
template<typename base_t>
class PersonImpl :
public PersonItf
{
public:
void SayHi() const override
{
std::cout << "Hi!\n";
}
};
template<typename base_t>
class ManImpl :
public ManItf
{
public:
void Shout() const override
{
std::cout << "Yohoohoooo!\n";
};
};
template<typename base_t>
class WomanImpl:
public WomanItf
{
public:
void Smile() const override
{
std::cout << "Smile!\n";
};
};
//-----------------------------------------------------------------------------
// now we can group capabilities together in classes
//
class Man :
public ManImpl<Man>
{
};
class Woman :
public WomanImpl<Woman>
{
};
class ManAndWoman :
public ManImpl<ManAndWoman>,
public WomanImpl<ManAndWoman>
{
};
//-----------------------------------------------------------------------------
// this Person class will check validity of the composition
// at compile time.
template<typename type_t>
struct Person :
public PersonImpl<type_t>,
public type_t
{
static_assert(!(std::is_base_of_v<WomanItf, type_t>&& std::is_base_of_v<ManItf, type_t>), "Being both a Man and a Woman is not correct in this program\n");
};
//-----------------------------------------------------------------------------
class Daniel : public Person<ManAndWoman> {};
class Santa : public Person<Man> {};
int main()
{
Daniel daniel;
Santa santa;
daniel.SayHi();
santa.Shout();
return 0;
}
uj5u.com熱心網友回復:
定義
#include <utility>
namespace Definer
{
// define
namespace Classification
{
class Person { unsigned int age; };
}
class Man : public Classification::Person {};
class Woman : public Classification::Person {};
// conditions
template <typename Derived>
static constexpr bool is_convertible_person()
{
constexpr bool result = std::is_convertible<Derived, Classification::Person>::value;
static_assert(result, "Person is duplicated.");
return result;
}
template <typename Derived>
concept Condition
= is_convertible_person<Derived>();
}
如何通過繼承使其成為可能
namespace Definer
{
template <typename Derived>
requires Condition<Derived>
class Requires
{};
}
class Daniel :
public Definer::Man,
public Definer::Requires<Daniel> // Not require, but similar
{};
比較班級規模。并犯錯。
class Compare :
public Definer::Man
{};
constexpr size_t size_of_Daniel = sizeof(Daniel); // 4U
constexpr size_t size_of_Compare = sizeof(Compare); // 4U
// This class make an error well, except for repeated occurrences.
class Santa :
public Definer::Man,
public Definer::Woman,
public Definer::Requires<Santa> // Not require, but similar
{};
//class Desire :
// public Definer::Man
// requires Definer::Condition<Desire> // It is not support now. I don't know if it will be possible later.
// 2021.12.20 c 20 preview
//{};
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/386956.html
下一篇:通過組合動態實作方法
