Có một mẫu mà tôi có thể kế thừa enum từ một enum khác trong C ++ không?
Đại loại vậy:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Có một mẫu mà tôi có thể kế thừa enum từ một enum khác trong C ++ không?
Đại loại vậy:
enum eBase
{
one=1, two, three
};
enum eDerived: public eBase
{
four=4, five, six
};
Câu trả lời:
Không thể. Không có thừa kế với enums.
Thay vào đó, bạn có thể sử dụng các lớp có tên int const.
Thí dụ:
class Colors
{
public:
static const int RED = 1;
static const int GREEN = 2;
};
class RGB : public Colors
{
static const int BLUE = 10;
};
class FourColors : public Colors
{
public:
static const int ORANGE = 100;
static const int PURPLE = 101;
};
Colors
các phiên bản lớp. Bạn chỉ sử dụng các giá trị int trong các thành viên const tĩnh.
Color
, giống như bạn có thể cho một enum
.
#include <iostream>
#include <ostream>
class Enum
{
public:
enum
{
One = 1,
Two,
Last
};
};
class EnumDeriv : public Enum
{
public:
enum
{
Three = Enum::Last,
Four,
Five
};
};
int main()
{
std::cout << EnumDeriv::One << std::endl;
std::cout << EnumDeriv::Four << std::endl;
return 0;
}
int basic(EnumBase b) { return b; }
và int derived(EnumDeriv d) { return d; }
, các kiểu đó sẽ không thể chuyển đổi thành int
, mặc dù các enums đơn giản. Và khi bạn cố gắng mã đơn giản, ngay cả như vậy như thế này: cout << basic(EnumBase::One) << endl;
, sau đó bạn sẽ nhận được một lỗi: conversion from ‘EnumBase::<anonymous enum>’ to non-scalar type ‘EnumBase’ requested
. Những vấn đề đó có thể được giải quyết quá mức bằng cách thêm một số toán tử chuyển đổi.
Bạn không thể làm điều đó trực tiếp, nhưng bạn có thể thử sử dụng giải pháp từ này bài viết.
Ý tưởng chính là sử dụng lớp mẫu trình trợ giúp chứa các giá trị enum và có toán tử ép kiểu. Xem xét rằng kiểu cơ bản cho enum là int
bạn có thể sử dụng lớp chủ này liền mạch trong mã của mình thay vì enum.
Thật không may, nó không thể thực hiện được trong C ++ 14. Tôi hy vọng chúng ta sẽ có một tính năng ngôn ngữ như vậy trong C ++ 17. Vì bạn đã có một số giải pháp thay thế cho vấn đề của mình nên tôi sẽ không cung cấp giải pháp.
Tôi muốn chỉ ra rằng từ ngữ nên là "mở rộng" chứ không phải "kế thừa". Phần mở rộng cho phép nhiều giá trị hơn (vì bạn đang nhảy từ 3 đến 6 giá trị trong ví dụ của mình) trong khi kế thừa có nghĩa là đặt nhiều ràng buộc hơn vào một lớp cơ sở nhất định để tập hợp các khả năng thu hẹp lại. Do đó, đúc tiềm năng sẽ hoạt động hoàn toàn ngược lại với kế thừa. Bạn có thể ép kiểu lớp dẫn xuất đến lớp cơ sở chứ không phải lớp phó với kế thừa lớp. Nhưng khi có các phần mở rộng, bạn "nên" có thể truyền lớp cơ sở đến phần mở rộng của nó chứ không phải là phần mở rộng. Tôi đang nói "nên" bởi vì, như tôi đã nói, một tính năng ngôn ngữ như vậy vẫn chưa tồn tại.
extends
là một từ khóa để thừa kế trong ngôn ngữ Eiffel.
Còn cái này thì sao? Được, một thể hiện được tạo cho mọi giá trị có thể, nhưng bên cạnh đó nó rất linh hoạt. Có bất kỳ nhược điểm nào không?
.h:
class BaseEnum
{
public:
static const BaseEnum ONE;
static const BaseEnum TWO;
bool operator==(const BaseEnum& other);
protected:
BaseEnum() : i(maxI++) {}
const int i;
static int maxI;
};
class DerivedEnum : public BaseEnum
{
public:
static const DerivedEnum THREE;
};
.cpp:
int BaseEnum::maxI = 0;
bool BaseEnum::operator==(const BaseEnum& other) {
return i == other.i;
}
const BaseEnum BaseEnum::ONE;
const BaseEnum BaseEnum::TWO;
const DerivedEnum DerivedEnum::THREE;
Sử dụng:
BaseEnum e = DerivedEnum::THREE;
if (e == DerivedEnum::THREE) {
std::cerr << "equal" << std::endl;
}
BaseEnum::i
công khai và BaseEnum::maxI
riêng tư.
Chà, nếu bạn định nghĩa enum
với cùng một tên trong lớp dẫn xuất và bắt đầu nó từ mục cuối cùng của đối tượng enum
trong lớp cơ sở, bạn sẽ nhận được hầu hết những gì bạn muốn - enum kế thừa. Nhìn vào mã này:
class Base
{
public:
enum ErrorType
{
GeneralError,
NoMemory,
FileNotFound,
LastItem,
};
};
class Inherited: public Base
{
public:
enum ErrorType
{
SocketError = Base::LastItem,
NotEnoughBandwidth,
};
};
Như đã nêu bởi bayda
, enum's không (và / hoặc không nên) có chức năng, vì vậy tôi đã thực hiện cách tiếp cận sau đây đối với vấn đề khó khăn của bạn bằng cách điều chỉnh Mykola Golubyev
phản ứng của:
typedef struct
{
enum
{
ONE = 1,
TWO,
LAST
};
}BaseEnum;
typedef struct : public BaseEnum
{
enum
{
THREE = BaseEnum::LAST,
FOUR,
FIVE
};
}DerivedEnum;
Bạn có thể sử dụng một dự án SuperEnum để tạo bảng liệt kê có thể mở rộng.
/*** my_enum.h ***/
class MyEnum: public SuperEnum<MyEnum>
{
public:
MyEnum() {}
explicit MyEnum(const int &value): SuperEnum(value) {}
static const MyEnum element1;
static const MyEnum element2;
static const MyEnum element3;
};
/*** my_enum.cpp ***/
const MyEnum MyEnum::element1(1);
const MyEnum MyEnum::element2;
const MyEnum MyEnum::element3;
/*** my_enum2.h ***/
class MyEnum2: public MyEnum
{
public:
MyEnum2() {}
explicit MyEnum2(const int &value): MyEnum(value) {}
static const MyEnum2 element4;
static const MyEnum2 element5;
};
/*** my_enum2.cpp ***/
const MyEnum2 MyEnum2::element4;
const MyEnum2 MyEnum2::element5;
/*** main.cpp ***/
std::cout << MyEnum2::element3;
// Output: 3
const int&
cho một đơn giảnint
Khá là hacky nhưng đây là điều tôi nghĩ ra nếu đối phó với enums có phạm vi:
enum class OriginalType {
FOO, // 0
BAR // 1
END // 2
};
enum class ExtendOriginalType : std::underlying_type_t<OriginalType> {
EXTENDED_FOO = static_cast<std::underlying_type_t<OriginalType>>
(OriginalType::END), // 2
EXTENDED_BAR // 3
};
và sau đó sử dụng như:
OriginalType myOriginalType = (OriginalType)ExtendOriginalType::EXTENDED_BAR;
Câu trả lời này là một biến thể của câu trả lời Brian R. Bondy. Vì đã được yêu cầu trong một bình luận, tôi sẽ thêm nó làm câu trả lời. Tôi không chỉ về việc nó có thực sự đáng giá hay không.
#include <iostream>
class Colors
{
public:
static Colors RED;
static Colors GREEN;
operator int(){ return value; }
operator int() const{ return value; }
protected:
Colors(int v) : value{v}{}
private:
int value;
};
Colors Colors::RED{1};
Colors Colors::GREEN{2};
class RGB : public Colors
{
public:
static RGB BLUE;
private:
RGB(int v) : Colors(v){}
};
RGB RGB::BLUE{10};
int main ()
{
std::cout << Colors::RED << " " << RGB::RED << std::endl;
}
enum xx {
ONE = 1,
TWO,
xx_Done
};
enum yy {
THREE = xx_Done,
FOUR,
};
typedef int myenum;
static map<myenum,string>& mymap() {
static map<myenum,string> statmap;
statmap[ONE] = "One";
statmap[TWO] = "Two";
statmap[THREE] = "Three";
statmap[FOUR] = "Four";
return statmap;
}
Sử dụng:
std::string s1 = mamap()[ONE];
std::string s4 = mymap()[FOUR];