我有一个基类和一个派生类。派生类具有一些其他功能,用户可以在他们正在访问的类之间进行切换。
class BaseClass {
private:
string valid_operations[2] = {"%", "#"};
};
class DerivedClass : BaseClass {
private:
string valid_operations[4] = {"!", "q", "%", "#"};
};
我想做的是实例化一个对象,并使用户能够在这两个对象之间互换。
例如:
BaseClass obj;
string input;
while (true) {
cin >> input;
if (input == "switch")
obj = DerivedClass();
else
obj.apply_action(input);
}
在C ++中有没有办法做到这一点?另外,有没有办法我可以在valid_operations
中将DerivedClass
声明为{"!", "q"} + BaseClass.valid_operations
?
答案 0 :(得分:1)
您不能使用数组变量来执行此操作,但是如果选择向量,则可以在基中声明它,然后在受保护的构造函数中进行初始化,如下所示:
ControlService()
请注意,该示例未使用一个派生类,而是建立了一个自己不具有任何操作的基础,并依靠子类在构造函数中提供操作列表。
还要注意,该实现使用自动存储功能在auto showError = []()
{
DWORD err = GetLastError();
qDebug() << "Restart PostgreSQL service failed. Error: " << err << "\n";
};
SERVICE_STATUS Status;
SC_HANDLE SCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!SCManager)
{
showError();
return;
}
SC_HANDLE SHandle = OpenService(SCManager, L"postgres", SERVICE_STOP | SERVICE_START | SERVICE_QUERY_STATUS);
if (!SHandle)
{
showError();
CloseServiceHandle(SCManager);
return;
}
if (!QueryServiceStatus(SHandle, &Status))
{
showError();
CloseServiceHandle(SHandle);
CloseServiceHandle(SCManager);
return;
}
if (Status.dwCurrentState != SERVICE_STOPPED)
{
qDebug() << "Stopping PostgreSQL service...\n";
if (!ControlService(SHandle, SERVICE_CONTROL_STOP, &Status))
{
showError();
CloseServiceHandle(SHandle);
CloseServiceHandle(SCManager);
return;
}
DWORD dwStartTime = GetTickCount();
DWORD dwTimeout = 30000; // 30-second time-out
DWORD dwWaitTime;
while (Status.dwCurrentState == SERVICE_STOP_PENDING)
{
qDebug() << "Waiting for PostgreSQL service to stop...\n";
dwWaitTime = Status.dwWaitHint / 10;
if (dwWaitTime < 1000)
dwWaitTime = 1000;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
Sleep(dwWaitTime);
if (!QueryServiceStatus(SHandle, &Status))
{
showError();
CloseServiceHandle(SHandle);
CloseServiceHandle(SCManager);
return;
}
if (Status.dwCurrentState != SERVICE_STOP_PENDING)
break;
if (GetTickCount() - dwStartTime > dwTimeout)
{
qDebug() << "Stop of PostgreSQL service timed out.\n";
CloseServiceHandle(SHandle);
CloseServiceHandle(SCManager);
return;
}
}
if (Status.dwCurrentState != SERVICE_STOPPED)
{
qDebug() << "Restart PostgreSQL service failed. Service did not stop.\n";
CloseServiceHandle(SHandle);
CloseServiceHandle(SCManager);
return;
}
qDebug() << "PostgreSQL service stopped successfully.\n";
}
if (!StartService(SHandle, 0, NULL))
showError();
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
中分配派生类,以方便使用。实际的实现几乎可以肯定会使用带有运算符class BaseClass {
private:
std::vector<string> valid_operations;
protected:
BaseClass(std::vector<string> vo) : valid_operations(vo) {}
public:
void ShowValidOperations() {
for (string op : valid_operations) {
std::cout << op << " ";
}
std::cout << std::endl;
}
};
class OptionOneDerived : public BaseClass {
public:
OptionOneDerived() : BaseClass({"%", "#"}) {
}
};
class OptionTwoDerived : public BaseClass {
public:
OptionTwoDerived() : BaseClass({"!", "q", "%", "#"}) {
}
};
int main() {
BaseClass *b;
OptionOneDerived a;
b = &a;
b->ShowValidOperations();
OptionTwoDerived c;
b = &c;
b->ShowValidOperations();
return 0;
}
和main
的动态分配。
答案 1 :(得分:1)
您可以在基类中将函数apply_action()
声明为虚函数。然后,您可以在派生类中重写该函数,并利用多态性。
class BaseClass {
public:
BaseClass(std::set<std::string> actions) : valid_operations(std::move(actions)) {}
virtual void apply_action(std::string action)
{
if (IsValid(action))
{
//Do stuff
}
}
protected:
bool IsValid(const std::string& action)
{
return valid_operations.find(action) != std::end(valid_operations);
}
private:
std::set<std::string> valid_operations;
};
class DerivedClass : public BaseClass {
public:
DerivedClass(std::set<std::string> actions) : BaseClass(actions) {}
virtual void apply_action(std::string action) override
{
if (IsValid(action))
{
//Do stuff
}
}
};
在您的main()
函数中或您想使用这些类的任何地方,您都可以创建这样的实例:
BaseClass base({ "%", "#" });
DerivedClass derived({ "!", "q", "%", "#" });
使用一个BaseClass*
指针,您可以切换以使用这些对象之一。多态性就是这样工作的:名称相同,但行为不同,取决于所使用的实际对象。使用BaseClass*
指针指向base
或derived
。