是否可以使用推导的返回类型声明纯虚函数?如果没有,为什么不呢?

时间:2015-08-14 02:46:45

标签: c++ c++14 auto decltype pure-virtual

我有一些抽象类,我想知道是否可以在其中声明一个带有此签名的函数:

virtual auto some_function() = 0;

如果它有助于回答,我试图实现一个允许为不同类型注册回调的类,这样当调用成员模板函数时,它将查找其参数' s { {1}}在关联容器中并在其上调用其关联的回调。

对问题原始性的理解

根据N3638 - Return type deduction for normal functions

  

可以允许虚拟的返回类型扣除   函数(...)

所以虽然在C ++中不允许自动虚拟,但根据Jason Merrill ,这是一种可能的替代设计。

所以这个问题:是否可以使用推导的返回类型声明纯虚函数?如果不是,为什么不呢?(我已修复标题以匹配真实问题及其意图)与问题的答案不一致是否可以声明具有推导返回类型的虚函数吗

如果主持人考虑问题而不仅仅是标题,也许会有所帮助。

1 个答案:

答案 0 :(得分:0)

这个问题没有意义。 auto表示从初始化推断:

auto i = 1; // int

或从return声明推断:

auto f() { return 2; } // int

纯虚函数按定义没有虚函数(*)的定义,所以它没有return语句,所以返回类型可以不能从任何内容中推断

您必须对C ++有不正确的理解才能认为这可行。

简答: C ++是静态输入的。

其他详细信息

注意(*):纯虚函数可以有定义,但它是    用范围调用的非虚函数的定义    解析算子:

struct Base {
    virtual void f() = 0;
};

void Base::f() {
    std::cout << "Base::f()\n";
}

struct Der : Base {
    virtual void f();
};

void Der::f() {
    cout << "Der::f()\n";
}

int main() {
    Der d;
    d.Base::f();
}

测试here;输出:

Base::f()

OTOH,Base::f()无法通过虚拟呼叫机制调用:

struct Base {
    Base ();
    virtual void f() = 0;
};

void call (Base *p) {
    cout << "Base::Base()\n";
    p->f();
}

Base::Base () {
    call(this);
}

测试here;生成:

Runtime error

无法虚拟调用纯虚函数。

纯虚函数返回类型可以从非虚拟定义(**)的return语句中推导出来,但它会创建另一个特例,它不会解决当前的问题(return语句是在基类中不知道。)

(**)虚拟函数不能在C ++中声明auto,但没有强烈的理由不允许auto虚函数。

回复评论

  

返回类型可以假设从派生类中推导出来。   实施

好的,我们说我们这样做:

struct Base {
    virtual auto f() = 0;
};

struct Der1 : Base {
    virtual int f();
};

那么Base::f()的返回类型是int,对吗?这假设Der可以在编译器中找到,即使它在后面定义,在其他地方,并且程序是单独编译的(或者你可能建议这个功能不兼容单独的编译?)。现在这个类可以在其他地方派生出来:

struct Der2 : Base {
    virtual std::string f();
};

那么Base::f()的返回类型是什么? int,string,both,both,cat

在C ++中,表达式必须具有明确定义的类型:声明的类型,又称编译时类型,又名静态类型。这些话是等价的。

例如,指针变量声明类型永远不会更改,而不是声明的*p类型,但真正的运行时动态类型*p取决于p的值:

Base *p = 0; 

// declared type of p is Base*, real type of *p is Base, 
// declared type of *p is Base, real type of *p is undefined
cout << "typeid (p): " << typeid (p).name() << "\n";

p = new Der1; 
// declared type of p is Base*, real type of *p is Base, 
// declared type of *p is Base, real type of *p is Der1
cout << "typeid (p): " << typeid (p).name() << "\n";
cout << "typeid (*p): " << typeid (*p).name() << "\n";

编译器使用声明的类型:

  • 用于名称查找
  • 用于重载解析(重载的非成员函数,重载的成员函数,重载的运算符)
  • 用于成员访问权检查(publicprotectedprivate

真实类型控制运行时虚拟呼叫行为。

声明与真实类型的区别是最重要的C ++概念之一!