c++ - 抽象函数(C++ 中的纯虚函数)可以阻止该类的实例化吗?它们是定义合约的一种方式吗?
问题描述
我不认为你可以用抽象函数实例化一个类,但我不确定。
此外,抽象函数是定义合约的一种方式,对吧?因为它们必须在子类中实现,类比合同。
此外,我还想知道抽象函数是否只能有一个或多个实现,以及它们是否可以存在于非抽象类中。我不认为它们可以存在于非抽象类中,因为抽象函数意味着一个类是抽象的,我相信抽象函数可以有多个实现。
解决方案
我不认为你可以用抽象函数实例化一个类,但我不确定。
你不能。
此外,我还想知道抽象函数是否只能有一个或多个实现,以及它们是否可以存在于非抽象类中。
这就是他们的全部目的。它们可以(无声地)出现在类层次结构中,具有抽象基础,因此也可以使派生类抽象。但最后它们必须在应该可实例化的派生类中实现。
我不认为它们可以存在于非抽象类中,因为抽象函数意味着一个类是抽象的,我相信抽象函数可以有多个实现。
纯虚函数(无论是继承的还是直接声明的)是使类抽象的原因。
正如你提到的合同:
一个纯粹的虚拟功能可以被认为是一个合同,是的。
在 c++ 中,它们通常用于声明如下接口
struct IMyInterface {
virtual void foo(int a, std::string b) = 0;
virtual int bar() = 0;
virtual ~IMyInterface() {}; // Note: Interfaces must have at least a
// virtual destructor function defined, but
// no other non pure virtual funcitons must
// be implemented.
};
一个类可以继承多个接口,其他类可以将其用作契约,而无需知道实现它的具体类。
// A class implementing the interface
class Baz : public IMyInterface {
virtual void foo(int a, std::string b) {
// Do something with a and b
// ...
}
virtual int bar() {
return 3 * 5;
}
virtual ~Baz() = default; // Default destructors aren't automatically virtual!
};
// Another class implementing the interface
class Twiddle : public IMyInterface {
virtual void foo(int a, std::string b) {
// Do something with a and b
// ...
}
virtual int bar() {
return 42;
}
virtual ~Twiddle() = default;
};
// A class using the interface
class Client {
public:
// The concrete implementation can be configured by passing
// the interface in the vonstructor
Client(IMyInterface* intf_) : intf(intf_) {}
void someMethod() {
intf->foo(42,"Hello universe!");
int x = intf->bar();
}
private:
IMyInterface* intf;
};
另一种方法是,在模板方法设计中使用它们。即一个抽象类,它实现了算法或某些行为,并依赖于继承类来实现它的基本部分。
class MyAbstractBase {
protected:
struct context {
int paramA;
std::string paramB;
};
int operateOnContext(const context& ctx) = 0;
public:
// Some behavior exposed to client classes
int doSomething() {
// Setup a context
context ctx { 42, "Hello universe!" };
return operateOnConetxt(ctx);
}
virtual ~MyAbstractBase() = default;
};
// An inherited class, which will write the context to a file
class Derived1 : public MyAbstractBase {
protected:
int operateOnContext(const MyAbstractBase::context& ctx) {
std::ofstream out("AFile.txt");
out << "Param A is:" << ctx.paramA << std::endl;
out << "Param B is:" << ctx.paramB << std::endl;
}
public:
virtual ~Derived1() = default;
};
// Another inherited class, which will send the context over a network connection
class Derived2 : public MyAbstractBase {
protected:
int operateOnContext(const MyAbstractBase::context& ctx) {
NetworkConn conn;
conn.connect("NetworkEndpoint");
conn.send(ctx.paramA);
conn.send(ctx.paramB);
conn.disconnect();
}
public:
virtual ~Derived2() = default;
};
推荐阅读
- sql - 需要重构 SQL Query 以通过 CPP 减少执行时间
- sql - SQL 语句:SET DATEFIRST 5
- angular - 跟踪数组内元素顺序的变化 - Angular 10
- encryption - 强制 gpg 使用特定的证书
- c# - 自定义标头(Microsoft.AspNet.WebApi.Versioning & Swagger)的 WebApi 版本控制不为使用相同路由的端点生成 Swagger 文档
- python - python中的列表和x?
- python - ModuleNotFoundError:python 3.9 中没有名为“scipy”的模块
- c# - Entity Framework Core 3:DBContext 上的接口好的做法?
- python - 当查询规范中有空格时,使用 Python 的 urllb2 查询 solr 请求
- jmeter - JMeter 记录每个 http 请求和响应以及详细信息报告