当基类要访问继承类的成员时
When base class wants to access member of an inherited class
这是我的情况:
我正在用c++编写一个由节点和边缘组成的数据结构。节点之间通过边连接。
我有不同类型的节点,例如文本节点或int节点。文本节点连接到文本节点,int节点连接到int节点。我使用继承来实现不同类型的节点,因为它是有意义的:基本上,所有节点都与其他节点相连,所以Node是基类,和TxtNode, IntNode是继承类,它们共享节点的基本属性。
然而,当我试图从继承节点获取连接的继承节点时,这会给我带来问题,因为获取函数(检索连接到调用节点的特定节点的函数)是在基类node中定义的。例如,从TextNode调用这个fetch函数返回TextNode的基本版本,它缺少额外的信息。
我不确定在这里做什么是明智的编码实践。我之所以选择这样编码,是因为必须为所有不同类型的节点定义不同的连接获取函数似乎没有意义。
如果还有什么我可以透露的,请告诉我。
这是我的代码,我试图打印一个继承节点的伙伴,但它会导致打印基本节点。
Node.cpp
#include "Node.h"
#include "Edge.h"
#include "common.h"
#include <vector>
#include <cassert>
#include <cstddef>
#include <stdint.h>
#include <iostream>
Node::Node() {
id = (intptr_t)this;
edges.clear();
}
int Node::connect(Node* dst) {
// establish link between calling node
// and dst node, first linkage will
// edge between each other, links after
// increments strength. returns number of
// links
// fetch edge connecting this node and
// dst node
Edge* edge = findDstEdge(dst);
// if the branch isn't established yet,
// then make connection
if (edge==NULL) {
establishConnection(dst, 1);
return 0;
} else {
edge->strengthenConnection();
return 1;
}
}
Edge* Node::findDstEdge(Node* dst) {
// fetches edge corresponding
// to destination node
// walk through vector of edges to find
// edge connecting to dst
vector<Edge*>::iterator iter = edges.begin();
while(iter!=edges.end()) {
Edge* e = *iter;
Node* partner = e->getPartner(this);
if (partner->getID() == dst->getID())
return e;
iter++;
}
// not found
return NULL;
}
void Node::establishConnection(Node* dst, int str) {
// low level node addition
// establish a new edge between
// nodes which don't know each other
Edge* e = new Edge(this, dst, str);
this->manuallyConnect(e);
dst->manuallyConnect(e);
}
void Node::manuallyConnect(Edge* e) {
edges.push_back(e);
}
ostream& operator<<(ostream& stream,Node n) {
vector<Edge*>::iterator iter = n.edges.begin();
while(iter!=n.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Node.h
#ifndef _NODE_H_
#define _NODE_H_
#include "common.h"
#include <vector>
#include <string>
#include <stdint.h>
class Edge;
using namespace std;
class Node {
protected:
vector<Edge*> edges;
intptr_t id;
public:
Node();
// manipulation
void establishConnection(Node* dst,
int str);
int connect(Node* dst);
Edge* findDstEdge(Node* dst);
// fetchers
intptr_t getID() {return id;}
vector<Edge*> getEdges() {return edges;}
void manuallyConnect(Edge* e);
friend ostream& operator<<(ostream& stream, Node n);
};
#endif
TxtNode.cpp
#include "TxtNode.h"
#include "Edge.h"
#include "common.h"
#include <iostream>
TxtNode::TxtNode(char c): Node() {
_c = c;
}
ostream& operator<<(ostream& stream, TxtNode tn) {
// print out character of this TxtNode
stream << "char: " << tn._c << endl;
stream << "id: " << tn.id << endl;
// print out all connections and its
// strength
vector<Edge*>::iterator iter = tn.edges.begin();
while(iter!=tn.edges.end()) {
Edge* e = *iter;
stream << *e << endl;
iter++;
}
return stream;
}
Edge.cpp
#include "Edge.h"
#include "Node.h"
#include "common.h"
#include <cassert>
#include <iostream>
using namespace std;
Edge::Edge(Node* a, Node* b, int str) {
node_a = a;
node_b = b;
strength = str;
}
void Edge::strengthenConnection() {
strength++;
}
Node* Edge::getPartner(Node* src) {
uint src_ID = src->getID();
if (node_a->getID() == src_ID)
return node_b;
else if (node_b->getID() == src_ID)
return node_a;
assert(false);
}
ostream& operator<<(ostream& stream, Edge e) {
stream << "strength: "
<< e.strength
<< endl;
stream << "node_a: "
<< e.node_a->getID()
<< endl;
stream << "node_b: "
<< e.node_b->getID()
<< endl;
return stream;
}
目前我只有代码来打印ID,这是一个intptr_t,因为我发现我不能从基类访问继承类的成员。
我倾向于从基类访问继承类的成员,因为边缘类处理基节点类。
如果有class代码就好了。
从你告诉你的,你不声明取函数为virtual。
下面是一个关于虚函数/非虚函数如何工作的快速示例
class baseNode {
public:
int fetch() { printf "fetched from base";};
}
class intNode : public baseNode {
public:
int fetch() { printf "fetched from derived int";};
}
class txtNode : public baseNode {
public:
int fetch() { printf "fetched from derived txt";};
}
以下代码
baseNode * ptr = new intNode();
ptr->fetch();
将打印" fetchedfrombase "
但是如果你声明取函数为virtual:
class baseNode {
public:
virtual int fetch() { printf " fetched from base";};
}
同样的代码将打印" fetchedfromderived int"
你写
“文本节点连接到文本节点,int节点连接到int节点。
那么你可以非常简单地将Node_
定义为一个类模板:
template< class Value >
struct Node_
{
vector<Node_*> connected_nodes;
Value value;
};
换句话说,使用编译时多态性,而不是动态多态性,以便在编译时获得相关的类型信息。
也就是说,一定要看看Boost。
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 如何从另一个文件继承私有成员变量和公共函数
- C++继承更改成员
- 继承和友元函数,从基类访问受保护的成员
- 删除C++继承中虚拟类成员的代码重复
- 成员包含其他继承类的继承类?
- 如何定义一个没有重复代码的继承的 const 类成员函数?
- 打印所有继承的类成员变量和方法
- 如何在复杂继承中访问静态成员变量
- enable_if继承的成员函数的名称查找错误
- 初始化依赖于子类的继承类的常量类成员
- 继承:调用基类的成员和方法
- 类设计:类成员继承自同一基类
- 使用 CRTP 进行选择性静态成员继承
- 具有'using'的模板模板成员继承
- 结构绑定:与公共数据成员(继承的基类)结合
- 为什么C++继承不允许基类的公共成员继承到派生类的私有成员?
- 静态成员继承和保护
- 是否可以检查是否为类定义了成员函数,即使该成员继承自未知基类
- 混合模板/非模板继承分类和成员继承