抽象基类,数据成员,构造函数和运算符重载

时间:2014-02-16 01:15:01

标签: c++ oop inheritance polymorphism copy-constructor

我有一个包含数据的抽象基类,我需要为这些数据分配内存,另一个问题是,衍生类有=运算符重载和复制构造函数,我想知道如何确保从类抽象基类复制成员数据的衍生类也将被复制,遵循代码示例:

class A {
public:
  A(const char* v) {
    value = new char[strlen(v)+1];
    strncpy(value, v, strlen(v));
  }

  A(const A &a) {
    value = new char[strlen(a.value)+1];
    strncpy(value, a.value, strlen(a.value));
  }

  virtual ~A() {
    delete[] value;
  }

  A& operator=(const A& a) {
    value = new char[strlen(a.value)+1];
    strncpy(value, a.value, strlen(a.value));
    return *this;
  }

  const char* get() const {
    return value;
  }

  virtual void do_some() = 0;
private:
  char *value;
};

class B: public A {
public:
  B(const char *v, const char *n) : A(v) {
    name = new char[strlen(n)+1];
    strncpy(name, n, strlen(n));
  }

  B(const B &b) : A(b) {
    name = new char[strlen(b.name)+1];
    strncpy(name, b.name, strlen(b.name));
  }

  ~B() {
    delete[] name;
  }

  B& operator=(const B& b) {
    A::operator=(b);
    name = new char[strlen(b.name)+1];
    strncpy(name, b.name, strlen(b.name));
    return *this;
  }

  const char *get() const {
    return name;
  }

  void do_some() {
    std::cout << name << std::endl;
  }

private:
  char *name;
};

我的疑问是,在一些C ++的书中说,重载operator =并在抽象基类中声明一个复制构造函数不是一个好主意,那么如何在deriate类中声明一个复制构造函数和operator =并确保基类被正确复制了吗?

在我的项目中,如果我不在抽象基类中使用数据成员,我必须在所有派生类中声明一些数据成员,当然这不止一个,所以我设计了带有数据成员的抽象类,但我不知道是否有更好的方法。

1 个答案:

答案 0 :(得分:1)

你正在做的事情有点尴尬,但技术上很好(除了通过在new[]之前删除赋值运算符中的名称和值而泄漏内存),但是只有你没有计划多重继承。这有点乱,可能就是为什么你所指的任何书都警告它,但你不应该在具有数据成员的类上使用多重继承(一般而言,尤其如此)。

您可能想尝试不同的方法。考虑在基类中使用受保护的辅助函数(或几个)来设置其变量:

class A
{
public:

// ...

private:
  char *value;

protected:
  void set_value(const char *str)
  {
    delete[] value; // remember, deleting null does nothing
    value = new char[strlen(str)+1];
    strncpy(value, str, strlen(str)); // Also, why do you need strncpy?
    // You'll get no null-terminator, which leads to major problems
    // Consider just strcpy(value, str);
  }
};

这样,您可以从任何派生类设置该值,该功能仍然是公共使用隐藏的,您不必为抽象类编写赋值运算符或复制构造函数。当你想到它时,真的没有多大意义,是吗?

它还可以避免这种情况:

A *a = new B;

B *b = new B;
(*a) = (*b); // ...with an assignment operator on A, this should compile.