在Go中,如果类型具有接口定义的所有方法,则可以将其分配给该接口变量,而不显式继承该接口变量。
是否可以在C / C ++中模仿此功能?
答案 0 :(得分:3)
是的,当然。
实际上,处理运行时接口的代码是用C语言编写的。 http://code.google.com/p/go/source/browse/src/pkg/runtime/iface.c
答案 1 :(得分:3)
是。您可以使用纯抽象类,并使用模板类来包装“实现”抽象类的类型,以便它们扩展抽象类。这是一个准系统的例子:
#include <iostream>
// Interface type used in function signatures.
class Iface {
public:
virtual int method() const = 0;
};
// Template wrapper for types implementing Iface
template <typename T>
class IfaceT: public Iface {
public:
explicit IfaceT(T const t):_t(t) {}
virtual int method() const { return _t.method(); }
private:
T const _t;
};
// Type implementing Iface
class Impl {
public:
Impl(int x): _x(x) {}
int method() const { return _x; }
private:
int _x;
};
// Method accepting Iface parameter
void printIface(Iface const &i) {
std::cout << i.method() << std::endl;
}
int main() {
printIface(IfaceT<Impl>(5));
}
答案 2 :(得分:0)
我想GObject可能会有一些粗略的对等。
答案 3 :(得分:0)
我为C ++做了一次尝试。我最终得到了一些有用的东西,但它是一个宏观马戏团:https://github.com/wkaras/c-plus-plus-misc/tree/master/IFACE。接口是两个指针,一个指向对象数据成员,另一个接口指向虚拟表(指向调用成员函数的thunk函数的指针结构)。这些表(不幸的是)在运行时生成。从接口到子接口的转换需要查找unordered_map,因此平均时间复杂度为O(1)。与将派生类指针/引用转换为基类相比,这是O(1)最坏情况。
它不是很有用,但它确实表明接口可以(干净地)添加到C ++,而且耗时相对较少。有些情况下,接口比基于继承的OO更好,而且只要试图保持C ++较小,那么牛就会远离谷仓。
答案 4 :(得分:0)
在 C++20 中有 conceps
,它们看起来很像 go 接口
https://en.cppreference.com/w/cpp/language/constraints
// Given the following data types
struct Type1 {
bool m(int i) {
return i > 0;
}
};
struct Type2 {
bool m(int i, int defaultArg = 0) {
return (i % 2) == defaultArg;
}
};
#include <iostream>
#include <string>
// I declare this concept
template<typename T>
concept HasUsefulMethod = requires(T a, int b) {
{ a.m(b) } -> std::same_as<bool>;
};
// So I can declare the following function that can take
// all classes that implement an m(int) -> bool
std::string calculateResult(HasUsefulMethod auto x, int i = 0){
return std::string {
x.m(i) ? "yes" : "no"
} + "!";
}
int main()
{
std::cout << "calculate result for struct Type1: " << calculateResult(Type1{}, -1) << std::endl;
std::cout << "calculate result for struct Type2: " << calculateResult(Type2{}) << std::endl;
}
我不想写这篇文章,因为我认为 C++ 的 concept
是一个非常有用的功能
它似乎即使使用默认参数也能工作,请参阅 Type2::m