如何使用带继承的std :: string作为参数?

时间:2013-06-26 00:16:29

标签: c++ inheritance polymorphism stdstring

我目前正在开发一个使用C ++的大学项目,其中一项任务是使用继承和多态来建立社交网络。目前我有一个Node类,用于 Map Multimap (两者都是手动创建的,不会从std中使用)。节点可以容纳两个变量(例如 key data ),在我使用它的地方,第一个变量可以是指针或字符串(它们让我们使用 std :: string )。

我遇到的问题是,当我从“root”类继承( Object )并使用“Object”作为“key”的数据类型时,我无法通过使用std作为其构造函数的参数创建的字符串,因为它不从我的Object类继承。一种解决方案是实现我自己的字符串类并使其继承自Object,但我正在寻找其他解决方法。

如果上述逻辑有任何问题,请告诉我,因为我刚刚开始使用C ++。

编辑1(我的节点的一些代码):

class TempNode
{
    private:
    TempNode* next;
Key key;
T value;
public:
TempNode();
explicit TempNode(const Key thisKey, const T thisValue, TempNode* thisNext = NULL)
: key(thisKey)
, value(thisValue)
, next(thisNext)
{
}
inline Key getKey() { return key; }
inline T getValue() { return value; }
inline TempNode* getNext() { return next; }
inline void setNext(TempNode* thisNext) { next = thisNext; }
};

字符串或人物类型目前仅在中使用,但这与另一个使用模板的实现(工作正常),但我的老师现在要求我们将继承应用于整个项目(我猜它已经习惯了。

3 个答案:

答案 0 :(得分:1)

要使用继承实现此功能,您可以将Key视为专门设计为地图/多图实现中的键的数据类型。 Key继承自Object,但它可以提供自己的,特定于键的函数,例如 - 函数repr(),它生成地图用于某些地图的表示 - 具体操作(可能作为散列或排序等的基础)。

地图/多图必须以Key个对象存储为指针(或std::unique_ptrstd::shared_ptr或其他任何适当的方式)的方式使用,但不能用作Key个对象的副本。

所以我们有:

struct Object
{
  virtual ~Object()
  { }
};

/* Key class. Pointers of this type are inserted
   into the map. */    
class Key : public Object
{
public:
  /* Must be supported by all keys: */
  virtual std::string repr() const = 0;
};

我们还假设Person个对象有一个单独的定义:

struct Person : Object
{
  Person(const std::string &name)
    : name_(name)
  { }

  std::string name_;
};

根据你的规范,有两种Key:一种代表字符串,必须用字符串初始化,另一种代表人,必须用人指针初始化(我假设person-keys实际上并不拥有这些指针,因此只要人员密钥存在,你需要确保他们指向的人对象保持活着。

我们通过将Key专门化为两个派生类PersonKeyStringKey来实现这一点:

class PersonKey : public Key
{
public:
  PersonKey(Person *person_ptr)
    : Key() , person_ptr_(person_ptr)
  { }

  virtual std::string repr() const
  {
    if (person_ptr_ != 0)
      return std::string("Person/") + person_ptr_->name_;
    else
      return "<NUL>";
  }

private:
  Person *person_ptr_;
};

class StringKey : public Key
{
public:
  StringKey(const std::string &str)
    : Key() , str_(str)
  { }

  virtual std::string repr() const
  {
    return str_;
  }

private:
  std::string str_;
};

当您在地图/多地图中插入广告时,会生成Key个对象(您表示为Key*Key&std::unique_ptr<Key>)。如果要插入字符串,可以将它们生成为StringKey个对象,当您想要将它们作为人物指针插入时,可以使用PersonKey - 但是您插入的键的数据类型不会反映专业化。

以下是一般Key对象的示例(实现为std::unique_ptr<Key>,但如果您不怕内存泄漏,则可以使用Key*):

int main()
{
  /* General key object: */
  std::unique_ptr<Key> mykey;

  /* Now it points to a string-key, initialized using
     a string, as required: */
  mykey.reset(new StringKey("hello"));
  std::cout << "repr(mykey) == \""
            << mykey->repr()
            << '"'
            << std::endl;

  /* Now the same key object is made to refer to
     a person object: */
  Person person("me");
  mykey.reset(new PersonKey(&person));
  std::cout << "repr(mykey) == \""
            << mykey->repr()
            << '"'
            << std::endl;

  return 0;
}

上述代码的必要标题是:

#include <iostream>
#include <memory>
#include <string>

(但memory仅在我使用std::unique_ptr时才需要,这对解决您的问题实际上并不是必需的。)

答案 1 :(得分:0)

我认为你真正想要的是模板。使用“根对象”的解决方案将无法使用标准对象和外部库,但您也无法使用带有基元的容器(例如person id(as int)作为键,Person类作为键)值)。

使用模板,您可以说明在编译时您将使用哪种类型,编译器将帮助您遵守自己的规则。它可以这样声明:

template<class T1, class T2>
class Map{
  T1 key;
  T2 value;
  (...)
}

然后你可以或多或少地使用它:

Map<std::String, int> phoneBook;

编译器会保护你并警告你,如果你试图添加,例如float而不是int,你就是Map。但在开始编码之前,我建议你先阅读一些教程,或者甚至一些关于c ++的书。但如果您现在想要开始使用通用,那么您可以启动她:

http://www.cplusplus.com/doc/tutorial/templates/

答案 2 :(得分:0)

您能够在Object变量中存储字符串的唯一方法是,如果字符串类继承自Object类,那么您将不得不实现自己的String类。

这里真正的缺陷是你正在采用Java / C#方法进行设计,其中一个Object变量可以容纳任何东西。在C ++中,处理此类事情的正确方法是使用模板,假设您的Map / Multimap / Node只需要保存一种特定的数据类型。

如果你的容器需要能够保存任何数据类型,我建议使用类型擦除,虽然这对于初学者来说可能有点复杂。