C++的委托构造和继承构造

一、介绍

学习C++的开发者都知道,在C++的类定义中,传统的会有常见的六个默认和构造相关的函数(不明白的可以去查一下资料)。但在实际情况中,经常会遇到一些具体的开发场景,只用这几个函数可能还是会导致重复代码的出现。开发者在学习编程之初,估计都会有人不断告诉你,只要有重复代码,就有优化的可能性。

但是,如果代码的重复到了最基础的阶段,开发者一般就无能为力了,即使使用了一些特殊的技巧,也会导致代码的可读性和可维护性的降低。本篇主要是分析构造函数在重载和继承时遇到的重复代码的问题。

二、委托构造函数(Delegating constructors)

委托构造函数非常好理解,就是一个构造函数委托(调用)另外一个构造函数来实现。这样做的好处是显而易见的,不需要在两个及以上的构造函数上写重复的代码。比如一个类中有两个以上的构造函数,他们都要对至少两个以上的相同变量进行赋值,那么委托构造函数的优势就体现出来。下面看一下代码,就清楚了:


#include <iostream>

class Example {
public:
  Example() : Example(0) {}
  //Example() : data_(d), len_(10), height_(10) {}//旧标准
  Example(int d) : data_(d), len_(10), height_(10) {}
  Example(const Example &ex) : Example(ex.data_) {}
  //旧标准,同上注释
  ~Example() {}

public:
  void Display() { std::cout << "data_,len_,heigth_ value:" << data_ << "," << len_ << "," << height_ << std::endl; }

private:
  int data_;
  int len_;
  int height_;
};
int main() {
  Example ex;
  ex.Display();
  Example ex1(ex);
  ex.Display();

  return 0;
}

上面的代码很清晰,不再多言。这里说明一下为什么拷贝构造函数使用传引用?一是值传递复制不断重复产生递归调用导致栈溢出;另外一个是提高效率,引用不需要再拷贝一个副本 。

三、继承构造函数(Inheriting Constructors)

和上面一样,如果在继承中出现类似的现象,即子类调用父类的数据对象大多重复并且自身基本不需要再次处理的,那么在传统的C++代码中还是需要手动一个个的写出来,而在C++11的继承构造函数出现后就可以简化使用。


class Base {
public:
  Base() : data_(3) {}
  Base(int d) : data_(d), len_(10), height_(10) {}
  Base(int d, int l, int h) : data_(d), len_(l), height_(h) {}

  void Display(int d) { std::cout << "cur vlaue is:" << d << std::endl; }
  void Display(int d1, int d2) { std::cout << "cur vlaue is:" << d1 + d2 << std::endl; }

protected:
  int data_;
  int len_;
  int height_;
};
class Derived : public Base {
public:
  using Base::Base;
  using Base::Display;
  //  Derived() {}
  //  Derived(int d) : Base(d) {}
  //  Derived(int d, int l, int h) : Base(d, l, h) {}
  void Display() { std::cout << "data_,len_,heigth_ value:" << data_ << "," << len_ << "," << height_ << std::endl; }
};

int main() {
  Derived d(2, 3, 6);
  d.Display();
  d.Display(2);
  d.Display(2, 3);

  return 0;
}

同样,被重名继承隐藏的函数,通过使用using也可以展现出来。
此处需要注意的是,C++是支持多重继承的,如果在多重继承里,则无法使用这种方式,只能老实的按老的方式,手动一个个的写代码。

四、总结

前面反复分析过,语言的发展一定是向简单和自然化推进,这是一个方向,不可逆转的。而C++标准的前进也是如此,上面的两个例子其实就是这样的。换句话说,如果现在看到编程时仍然有重复的或者不方便的地方甚至啰嗦的地方,在未来的新标准中,一定会修正。无数的例子已经出现了,这个只要跟着标准前进的开发者都深有体会。