我正在尝试用 C++ 编写二叉树实现,并使用 Google Test 对其进行测试。为了测试中序遍历,我对 BTree
类进行了子类化,这样我就可以覆盖 visit()
方法,这样我就可以输出到一个字符串到控制台。问题是我想使用现有的逻辑将新节点插入到树中,它插入的是基类而不是派生类,即使我将派生对象的指针传递给 insert()
方法。有没有办法让它为所有节点插入派生类?
这是测试用例:
TEST_F(BTreeTestSuite, inOrder)
{
class InOrderTest : public BTree
{
public:
InOrderTest(int data) throw(int) : BTree(data), itsVisitString() {};
virtual ~InOrderTest() {};
std::string visitString(void) const { return itsVisitString; }
virtual void visit()
{
std::ostringstream oss;
oss << itsData;
itsVisitString += oss.str();
std::cerr << "vs1: " << itsVisitString << '|' << std::endl;
itsVisitString += " ";
std::cerr << "vs2: " << itsVisitString << '|' << std::endl;
}
private:
std::string itsVisitString;
};
InOrderTest iot(20);
iot.insert(new InOrderTest(30));
iot.insert(new InOrderTest(15));
iot.insert(new InOrderTest(10));
iot.inOrder();
EXPECT_STREQ("10 15 20 30 ", iot.visitString().c_str());
}
下面是基类的相关部分:
class BTree
{
public:
BTree(int data) throw(); // constructor(s)
~BTree() throw(); // destructor
virtual void insert(BTree *node);
unsigned count() const;
void inOrder();
virtual void visit();
int data() const throw() { return itsData; };
BTree *left() const throw() { return itsLeft; };
BTree *right() const throw() { return itsRight; };
protected:
int itsData;
private:
// Don't allow creation of BTree without data
BTree() throw(); // constructor(s)
BTree *itsLeft;
BTree *itsRight;
};
...
BTree::BTree(int data) throw() : itsData(data)
{
itsLeft = itsRight = 0;
}
void BTree::insert(BTree *node)
{
if (node->itsData < itsData)
{
std::cerr << "Inserting data on the left\n";
if (itsLeft)
{
itsLeft->insert(node);
}
else
{
itsLeft = new BTree(node->itsData);
}
}
if (node->itsData > itsData)
{
std::cerr << "Inserting data on the right\n";
if (itsRight)
{
itsRight->insert(node);
}
else
{
itsRight = new BTree(node->itsData);
}
}
/* Drop value if it already exists in tree. */
}
void BTree::inOrder()
{
if (itsLeft) itsLeft->inOrder();
visit();
if (itsRight) itsRight->inOrder();
}
void BTree::visit()
{
cout << "base-visit: " << itsData << endl;
}
最佳答案
问题出在您的 BTree::insert
方法中。即使它获得了 InOrderTest *
,您也正在从这两行中创建 BTree
的实例:
void BTree::insert(BTree *node)
{
// logic checks...
itsLeft = new BTree(node->itsData);
// more logic checks...
itsRight = new BTree(node->itsData);
//...
}
您可以采用两种方法来解决此问题。您可以只使用传入的节点而不是构造新对象。在这种情况下,您的根节点拥有其子节点的所有权,并应负责适本地解除分配它们。由于您的单元测试正在执行 new InOrderTest
而没有匹配的 delete
,因此这种方法可行。
第二种方法是创建一个虚拟的clone
方法并让您的派生类处理它自己的创建。
class BTree
{
// BTree stuff
public:
virtual BTree* BTree::clone() const;
// more stuff
};
class InOrderTest : public BTree
{
public:
InOrderTest* clone() const { return new InOrderTest(*this); }
};
此外,如果您希望使用 BTree
的客户端代码从它派生,则将 BTree::~BTree
析构函数设为虚拟。 (参见 Effective C++ item#7)
关于c++ - Google Test 中调用的基本方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16727037/