除了C++;Dave Abrahams和Chris Diggins的界面创意 我最近在我的公司继承了一个遗留仿真框架,它是在2000年早期编写的,主要作者是从C和FORTRAN向C++过渡。接口/实现架构遵循Dave Abrahams和Chris Diggins在以下两个地方提出的想法:

除了C++;Dave Abrahams和Chris Diggins的界面创意 我最近在我的公司继承了一个遗留仿真框架,它是在2000年早期编写的,主要作者是从C和FORTRAN向C++过渡。接口/实现架构遵循Dave Abrahams和Chris Diggins在以下两个地方提出的想法:,c++,c++11,interface,architecture,implementation,C++,C++11,Interface,Architecture,Implementation,本文解释了用于允许该接口的技术 引用类型在提供匹配的任何类型上都是多态的 函数签名。 简介 我的上一篇文章,多态性 在没有规划的情况下,讨论了OOTL(面向对象模板 库)使用由BIL(Boost接口)实现的技术 库),它包含在OOTL版本0.1中。这 让很多人对引擎盖下发生的事情感到好奇 背景 BIL允许实现一组 与要引用的已声明接口的函数相匹配的函数 使用单一类型: class Dog { public: const char* MakeSound() { return "woo

本文解释了用于允许该接口的技术 引用类型在提供匹配的任何类型上都是多态的 函数签名。
简介
我的上一篇文章,多态性 在没有规划的情况下,讨论了OOTL(面向对象模板 库)使用由BIL(Boost接口)实现的技术 库),它包含在OOTL版本0.1中。这 让很多人对引擎盖下发生的事情感到好奇

背景
BIL允许实现一组 与要引用的已声明接口的函数相匹配的函数 使用单一类型:

class Dog {   
public:
    const char* MakeSound() { return "woof"; } 
};

class Duck {   
public:
    const char* MakeSound() { return "quack"; }
};

BOOST_IDL_BEGIN(IAnimal)
BOOST_IDL_FXN0(MakeSound, const char*)
BOOST_IDL_END(IAnimal)

int main() {   
    Dog dog;   
    Duck duck;   
    IAnimal animal = dog;  
    puts(animal.MakeSound()); // prints woof   
    animal = duck;  
    puts(animal.MakeSound()); // prints quack   
    return 0; 
}; 
问题 我经常被问到的问题是,实际上我们如何能够静态地 在C++中键入接口,而不在其中放置任何额外信息 反对

双宽度指针
为了实现任何一种动态 调度,我们需要在代码中的某个地方进行函数表查找, 否则我们就不能有运行时多态性。这个 然后,接口引用在内部表示为双倍宽度 指针;一个指针指向对象,而另一个指针指向对象 指向函数表。此函数表是静态创建的 在编译时使用模板

为每个类创建一个函数表,以转换接口类型 密码。这是使用任务的模板版本完成的 运算符和初始化构造函数

手动创建接口引用类型
Boost-Consulting.com的Dave Abrahams将以下代码发布到 2004年04月25日的Std.c++,这是我原创的一个进步。 接口代码生成工具使用的技术 HeronFront

// a baz "interface" 
class baz {  
private:
// forward declarations
    template <class T>
    struct functions;

 public:
    // interface
    template <class T>
    baz(T& x) : _m_a(&x), _m_t(&functions<T>::table)
    {}

int foo(int x)
{ return _m_t->foo(const_cast<void*>(_m_a), x); }

int bar(char const* x)
{ return _m_t->bar(const_cast<void*>(_m_a), x); }

private:
// Function table type for the baz interface
struct table_type
{
    int (*foo)(void*, int x);
    int (*bar)(void*, char const*);
};

// For a given referenced type T, generates functions for the
// function table and a static instance of the table.
template <class T>
struct functions
{
    static baz::table_type const table;

    static int foo(void* p, int x)
    { return static_cast<T*>(p)->foo(x); }

    static int bar(void* p, char const* x)
    { return static_cast<T*>(p)->bar(x); }
};

void const* _m_a;
table const* _m_t; };

template <class T> baz::table_type const baz::functions<T>::table = 
    {
         &baz::functions<T>::foo   , &baz::functions<T>::bar 
    };

struct some_baz {
    int foo(int x) { return x + 1; }
    int bar(char const* s) { return std::strlen(s); } 
};

struct another_baz {
    int foo(int x) { return x - 1; }
    int bar(char const* s) { return -std::strlen(s); } 
};

int main() {
    some_baz f;
    another_baz f2;
    baz p = f; 
    std::printf("p.foo(3) = %d\n", p.foo(3));
    std::printf("p.bar('hi') = %d\n", p.bar("hi"));
    p = f2;
    std::printf("p.foo(3) = %d\n", p.foo(3));
    std::printf("p.bar('hi') = %d\n", p.bar("hi")); 
} 
//一个baz“接口”
类baz{
私人:
//转发声明
模板
结构函数;
公众:
//接口
模板
baz(T&x):_m_a&x),_m_T(&functions::table)
{}
intfoo(intx)
{return _m_t->foo(const_cast(_m_a),x);}
整型条(字符常量*x)
{return{mu_t->bar(const_cast({mu a),x);}
私人:
//baz接口的功能表类型
结构表类型
{
整数(*foo)(无效*,整数x);
整型(*bar)(空*,字符常量*);
};
//对于给定的引用类型T,为
//函数表和表的静态实例。
模板
结构函数
{
静态baz::table_类型const table;
静态intfoo(void*p,intx)
{return static_cast(p)->foo(x);}
静态整型条(void*p,char const*x)
{return static_cast(p)->bar(x);}
};
无效常数*\u m\u a;
表const*\u m\t;};
模板baz::表类型const baz::函数::表=
{
&baz::functions::foo,&baz::functions::bar
};
构造一些东西{
intfoo(intx){返回x+1;}
int-bar(char-const*s){return std::strlen(s);}
};
构造另一个_baz{
intfoo(intx){返回x-1;}
int-bar(char-const*s){return-std::strlen(s);}
};
int main(){
一些_bazf ;;
另一个_baz f2;
baz p=f;
标准::printf(“p.foo(3)=%d\n”,p.foo(3));
标准::printf(“p.bar('hi')=%d\n”,p.bar(“hi”);
p=f2;
标准::printf(“p.foo(3)=%d\n”,p.foo(3));
标准::printf(“p.bar('hi')=%d\n”,p.bar(“hi”);
} 
关于代码 上面的代码手动定义了一个名为
baz
的接口引用, 它可以引用提供与
baz::表中的函数指针

每个接口引用变量都存储指向其函数的指针 通过变量
baz::_m_t
存储一个指向 对象位于
baz::_m_a

代码的作用是为每个类生成一个静态函数表 传递给
baz
T
。这些静态函数表具有
baz::table_type
和被命名为
baz::function::table
。尽管 只有一个名称,因为它是的静态模板变量
baz::function
,为每个
baz::函数
。换句话说,我们使用编译器生成 每个类接口对的函数表 编译时

摘要 所描述的技术,即使是复杂的,也是 仍然需要简化BIL的实施方式。比尔是 更为复杂,因为它还提供了对广泛应用程序的支持 一系列技术,如面向方面编程、委托、, 泛型编程等等。BIL还需要解决以下问题: C++预处理器的某些局限性。我会在未来写更多 随着BIL的成熟,并正式发布到 公共领域。希望本文能够帮助解释 技术背后的理论,可以为您提供一些关于 接口引用类型

<> Pr>框架的架构在过去几年里一直为我们服务,但是由于我们最终拥有了比使用Red Hat默认的更安全的现代编译器,所以我想开始升级框架以使用现代C++。
是否有人有更好的方法来设计支持动态多态性的接口/实现体系结构?

不确定这是否是您想要的:

// a baz "interface" 
class baz {  
private:
    struct IWrapper
    {
        virtual ~IWrapper() = default;
        virtual int foo(int) = 0;
        virtual int bar(const char*) = 0;
    };

    template <typename T>
    struct Wrapper : IWrapper
    {
        T& t;

        Wrapper(T& t) : t(t) {}
        int foo(int n) override { return t.foo(n); }
        int bar(const char* s) override { return t.bar(s); }
    };

    std::unique_ptr<IWrapper> wrapper;

 public:
    // interface
    template <class T>
    baz(T& x) : wrapper(std::make_unique<Wrapper<T>>(x)) {}

    int foo(int x) { return wrapper->foo(x); }
    int bar(char const* x) { return wrapper->bar(x); }
};
//一个baz“接口”
类baz{
私人:
str
#include <iostream>
#include <functional>

class Dog {   
public:
    const char* MakeSound() { return "woof"; } 
};

class Duck {   
public:
    const char* MakeSound() { return "quack"; }
};

struct IAnimal {
  template<class T>
  IAnimal(T& t) : MakeSound{ [&t]{return t.MakeSound();}}
  {}

  std::function<const char*()> MakeSound;
};

int main() {   
    Dog dog;   
    Duck duck;   
    IAnimal animal = dog;  
    std::cout << animal.MakeSound() << std::endl; // prints woof   
    animal = duck;  
    std::cout << animal.MakeSound() << std::endl; // prints quack   
    return 0; 
};