继承,选择性方法执行
Inheritance, selective method execution
我看了一个视频,可以在https://www.youtube.com/watch?v=4F72VULWFvc,我真的很喜欢其中一些案例的概念。但是我正在使用链表,需要选择方法执行,例如:
#include <stdio.h>
class A {
public:
A() : next(0) {
if (head == 0) {
head = this;
} else {
A* step = head;
while (step->next != 0) {
step = step->next;
}
step->next = this;
}
}
virtual ~A() {
if (head == this) {
head = 0;
} else {
A* step = head;
while (step->next != this) {
step = step->next;
}
step->next = next;
}
}
virtual void foo() {
// Do nothing...
}
static A* head;
A* next;
};
class B : public A {
public:
B() {}
virtual ~B() {}
virtual void foo() {
printf("function foon");
}
};
A* A::head = 0;
int main() {
A a_cls;
B b_cls;
A* step = A::head;
while (step != 0) {
step->foo();
step = step->next;
}
return 0;
}
实例化所有对象后,需要执行B
类对象的方法foo()
。为此,在A类中添加虚方法foo()
,空方法体virtual void foo() {}
;在B类中,在foo()
方法体中添加代码。
它工作,但我不喜欢它,在主函数中,它看起来像你在每个节点做一些事情,但你不是,它几乎感觉像一个空指针。是否有其他创造性的解决方案?
注意:我使用的是c++ 03.
查看dynamic_cast作为检查特定派生类型的方法,并且只在类B
(或从B
派生的类)的对象上调用foo
:
int main() {
A a_cls;
B b_cls;
A* step = A::head;
B* step_b = 0;
while (step != 0) {
step_b = dynamic_cast<B *>(step);
if (step_b != 0) {
step_b->foo();
}
step = step->next;
}
return 0;
}
这样,就不需要在A
上定义一个空的foo
方法。在ideone上试试。
它工作,但我不喜欢它,在主要功能,它看起来像你在每个节点做一些事情,但你没有
实际上你在每个节点上都做了一些。你所做的就是决定什么都不做。决策通常不是自由的,您还没有告诉我们足够的应用程序信息,以证明可以以一种决策可以有效自由(在编译时做出)的方式进行重构的猜测是正确的。
如果什么都不做的决定不可能是自由的,那么将该决定作为对虚函数的调用来实现几乎是该决定可能的最低成本。
它工作,但我不喜欢它,在
main
函数看起来像你在每个节点做的事情,但你不是,它几乎感觉像一个NULL
指针。是否有其他创造性的解决方案?
确保你的基类是一个纯抽象类。这样,每次调用step->foo();
都很可能会做一些事情。
这是一个异构列表的基本示例。List::Node
是一个抽象基类。List::Node::print()
是一个虚成员函数,只在具体类中实现。List
可以使用一个泛型算法来遍历Node
s,而不需要明确知道它所包含的Node
s的种类。
#include <iostream>
#include <string>
class List
{
public:
class Node
{
public:
Node() : next(nullptr) {}
virtual ~Node() {}
virtual void print() = 0;
Node* next;
};
List() : head(nullptr), tail(nullptr) {}
~List()
{
Node* node = head;
Node* next = nullptr;
for ( ; node != nullptr; node = next )
{
next = node->next;
delete node;
}
}
void addNode(Node* node)
{
if (head == 0)
{
head = tail = node;
return;
}
if ( head == tail )
{
head->next = node;
}
tail->next = node;
tail = node;
}
void print()
{
Node* node = head;
for ( ; node != nullptr; node = node->next )
{
node->print();
std::cout << std::endl;
}
}
Node* head;
Node* tail;
};
class NodeA : public List::Node
{
public:
NodeA(int d) : data(d) {}
virtual ~NodeA() {}
virtual void print()
{
std::cout << "In NodeA::print(), Data: " << data;
}
private:
int data;
};
class NodeB : public List::Node
{
public:
NodeB(double d) : data(d) {}
virtual ~NodeB() {}
virtual void print()
{
std::cout << "In NodeB::print(), Data: " << data;
}
private:
double data;
};
class NodeC : public List::Node
{
public:
NodeC(std::string const& d) : data(d) {}
virtual ~NodeC() {}
virtual void print()
{
std::cout << "In NodeC::print(), Data: " << data;
}
private:
std::string data;
};
int main()
{
List list;
list.addNode(new NodeA(10));
list.addNode(new NodeB(23.45));
list.addNode(new NodeC("abcd"));
list.print();
return 0;
}
尽管Austin的解决方案非常好,但在这种情况下,另一种方法(我通常更喜欢)是使用接口类和上转换。
class FooFighter { public: virtual void foo() = 0; };
class A { ... };
class B1 : public A { ... };
class B2 : public A, public FooFighter { ... };
...
int main() {
std::vector<A *> v;
// fill up v
for (int i = 0; i < v.size(); ++i) {
FooFighter * ff = dynamic_cast<FooFighter *>(v[i]);
if (ff) ff.foo();
}
return 0;
}
这让你保持一个类是否有足够独立于你的层次结构的其余部分。特别是,通过检查任何类型的类层次结构,你总是知道该类型是否实现了foo,因为它必须继承自FooFighter。当您使用向下转换方法时,您可以有A的多个子节点,它们以不同的方式非平凡地实现foo。这种方法还可以很好地配合ide,让您可以轻松地检查和遍历代码中的类型层次结构。
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 如何使父类不重复已经执行的祖父方法
- 如何将带有参数的方法传递给线程以执行?
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- 在 c++ 中从执行的 shell 命令获取返回状态的安全方法是什么?
- 在高通六边形处理器的word32上执行水平求和的最快方法是什么
- 在C++中执行方法的同一行中传递指针
- 在 MySQL 连接器C++ API 中使用一个函数调用执行多个查询的正确方法是什么?
- 如何执行重写的方法C++
- 基于整数向量执行位排列的有效方法?
- 执行模板参数包指向的所有方法
- cppUnit:针对多个测试方法执行一次的设置函数
- C++对象的 WMI 执行方法
- 为什么在从线程执行方法时使用QMetaObject::invokeMethod
- 执行方法调用时,有什么理由不C++中添加嵌套类/结构解析
- 有没有办法让C++类在开始执行析构函数之前自动执行方法
- 分段错误执行方法
- 只要发现字符,C++就会搜索并执行方法