是否有可能在C / C ++中模仿Go接口?

时间:2012-01-23 10:24:29

标签: go

在Go中,如果类型具有接口定义的所有方法,则可以将其分配给该接口变量,而不显式继承该接口变量。

是否可以在C / C ++中模仿此功能?

5 个答案:

答案 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

https://wandbox.org/permlink/gvlr0nFi56El8vcu