C++中Covariant返回值类型详解

 更新时间:2022年09月09日 10:55:49   作者:ithiker  
这篇文章主要介绍了C++中Covariant返回值类型详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以可以参考一下

前言

C++中当子类覆写(override)父类虚函数时,子类函数的返回值类型可以和父类函数的返回值类型不一致吗?
先说结论:可以,但当且仅当它们的返回值类型是协变返回值类型(Covariant)时可以。C++中gcc从3.4开始支持这一特性。

什么是协变返回值类型(Covariant)

函数的协变返回值类型指的是子类中的成员函数的返回值类型不必严格等同与该函数所重写的父类中的函数的返回值类型,而可以是更 “狭窄” 的类型。C++/Java等面向对象编程语言均支持协变返回值类型。

例子:

class Shape {
public:
  virtual ~Shape() { }          
  virtual Shape* clone()  const = 0;   // Uses the copy constructor
  virtual Shape* create() const = 0;   // Uses the default constructor
};
class Circle : public Shape {
public:
  Circle* clone()  const;   // Covariant Return Types; see below
  Circle* create() const;   // Covariant Return Types; see below
 
};
Circle* Circle::clone()  const { return new Circle(*this); }
Circle* Circle::create() const { return new Circle();      }

C++中不支持virtual constructor,因为:

  • 创建对象时需要知道对象的完整信息
  • 虚函数机制也决定了对象尚未创建时,类的virtual table或许还不存在
  • 我们不可能有指向virtual constructor的指针

但是我们可以通过上面的代码实现类似的想法,如果我们拥有指向对象的指针:

  • 通过clone()调用对象的拷贝构造函数,复制当前的对象
  • 通过create()调用默认构造函数,创建新的对象

比如下面的使用场景:

void userCode(Shape* s)
{
  Shape* s2 = s->clone();
  Shape* s3 = s->create();
  // ...
  delete s2;   
  delete s3;
}

如果指针指向的是基类对象,调用上述函数时返回的就是指向基类对象的指针并赋值给s2/s3,如果指针指向的是子类对象,调用上述函数时返回的就是指向子类对象的指针并赋值给s2/s3。

协变返回值类型(Covariant)的作用

协变返回类型到底有什么用呢,编译器为什么要支持这种语法?如果编译器不支持,上面的例子将只能写成如下这样:

class Shape {
public:
  virtual ~Shape() { }          
  virtual Shape* clone()  const = 0;   // Uses the copy constructor
  virtual Shape* create() const = 0;   // Uses the default constructor
};
class Circle : public Shape {
public:
  Shape* clone()  const;   // Covariant Return Types; see below
  Shape* create() const;   // Covariant Return Types; see below
 
};
Shape* Circle::clone()  const { return new Circle(*this); }
Shape* Circle::create() const { return new Circle();      }

这样上面的userCode函数将不能通过编译,上面调用clone函数部分将不得不改写成下面这样:

 void userCode(Shape* s)
{
  Shape* s2 = s->clone();
  Circle* c = dynamic_cast<Circle*>(s2);
  if (c != NULL) {
     // c point to Circle
  } else {
	  if (s2 != NULL) {
	     // s2 point to base Shape
	     }
	  }
  }
  // ...
  delete s2;   
}

通过if/else分支来判断s是指向子类Circle还是指向基类Shape,失去了动态绑定的意义。

到此这篇关于C++中Covariant返回值类型详解的文章就介绍到这了,更多相关C++ Covariant内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C/C++ extern和static的使用详解

    C/C++ extern和static的使用详解

    这篇文章主要介绍了C/C++ extern和static的使用,在讲到extern和static的时候先了解一下定义和声明的基本概念,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • C/C++编程判断String字符串是否包含某个字符串实现示例

    C/C++编程判断String字符串是否包含某个字符串实现示例

    这篇文章主要为大家介绍了C++编程中判断String字符串是否包含某个字符串的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2021-11-11
  • C++使用泛型导致的膨胀问题

    C++使用泛型导致的膨胀问题

    这篇文章主要介绍了C++使用泛型导致的膨胀,智能家居主机的嵌入式平台上使用C++进行开发。FLASH存储空间有限,这是必须要考虑的因素,一定要重视,下面我们一起进入文章看看详细内容
    2021-11-11
  • C/C++ ip地址与int类型的转换实例详解

    C/C++ ip地址与int类型的转换实例详解

    这篇文章主要介绍了C/C++ ip地址与int类型的转换实例详解的相关资料,这里提供了实例代码,实现思路及实现方法,需要的朋友可以参考下
    2016-12-12
  • C++成员解除引用运算符的示例详解

    C++成员解除引用运算符的示例详解

    这篇文章主要介绍了C++成员解除引用运算符,本例子在编译期间给指针赋值,在更为复杂的类中,可以使用指向数据成员和方法的成员指针,需要的朋友可以参考下
    2022-01-01
  • windows下用c++获取本机ip地址的三种方法

    windows下用c++获取本机ip地址的三种方法

    工作过程中遇到一个需求,需要获取本机ip地址,同时获取本机网络连接情况,即网线是否连接,经过多番搜索,本文给大家介绍了3种方案,通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • C语言的编程之美之内存函数

    C语言的编程之美之内存函数

    这篇文章主要介绍了C语言全部内存操作函数的实现详细讲解,作者用图文代码实例讲解的很清晰,有感兴趣的同学可以研究下
    2021-09-09
  • C++中使用function和bind绑定类成员函数的方法详解

    C++中使用function和bind绑定类成员函数的方法详解

    这篇文章主要介绍了C++中使用function和bind绑定类成员函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • C语言实现的程序员老黄历实例

    C语言实现的程序员老黄历实例

    这篇文章主要介绍了C语言实现的程序员老黄历,涉及日期的判定及流程控制的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • c语言中缺省参数的类型总结

    c语言中缺省参数的类型总结

    在本篇文章里小编给大家整理了一篇关于c语言中缺省参数的类型总结内容,有兴趣的朋友们可以跟着学习参考下。
    2021-09-09

最新评论