和大家圣诞快乐!
我正在学习静态多态性,并且正在阅读Andrei Alexandrescu关于基于策略的设计的出色著作。我在代码中遇到了以下内容:我有一个接口Interface,指定Foo必须存在该方法。该接口将由class实现Impl。我有以下两种选择:
1)动态多态
class Interface {
public:
virtual void Foo() = 0;
}
class Impl : public Interface {
public:
void Foo() {};
}
Run Code Online (Sandbox Code Playgroud)
2)静态多态
class Impl {
{
public:
void Foo() {};
}
template <class I>
class Interface : public I
{
public:
void Foo() { I::Foo(); } //not actually needed
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下使用静态多态性有意义吗?与第一种方法相比,第二种方法有什么好处吗?该接口仅指定了某些方法的存在,并且其机制对于不同的实现是相同的-因此与书中描述的情况不太一样,因此我觉得我可能只是在使事情变得过于复杂。
更新:我在运行时不需要多态行为;在编译时已知正确的实现。
c++ polymorphism templates policy-based-design static-polymorphism
下面是我理解为静态多态的一个非常简单的例子.为什么我不使用动态多态的原因是,我不想妨碍函数的内联PROCESSOR在op.
template <class PROCESSOR>
void op(PROCESSOR* proc){
proc->doSomething(5);
proc->doSomethingElse();
}
int main() {
ProcessorY py;
op<ProcessorY>(&py);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个例子的问题是:没有明确定义a PROCESSOR必须定义的函数.如果缺少一个,您将收到编译错误.我认为这是不好的风格.
它还有一个非常实际的缺点:IDE的在线帮助当然不能向您展示该对象上可用的功能.
什么是定义公共接口的好/官方方式PROCESSOR?
我不明白为什么我不能构建一个看起来像[1,"1",1.1]haskell 的列表.我不认为它是静态类型阻碍因为我认为head现在会有一个不明确的类型,但后来我想到了它并没有理由运行时系统不会实例化不同版本的head任何时候list被输入到它中,因此head [1,"1",1.1]将被输入List->Int,head (tail [1,"1",1.1])并将被输入为List->String.由于运行时已经进行了大量的簿记,为什么它不提供各种前奏函数的更好的多态(或它是通用的)版本?我在这里错过了什么?
我正在实现一个静态多态:
template<typename T>
class Base {
public:
void method() {
// do something
impl();
// do something else
}
void impl() { // intended to be private
static_cast<T*>(this)->impl();
}
};
class Derived : public Base<Derived> {
public:
void impl() { // intended to be private
}
};
Run Code Online (Sandbox Code Playgroud)
此代码是动态多态类的静态实现,其中 void impl() 是虚拟和私有的。
我已经实现了多态性(静态)。但是我必须将方法 void impl() 设为 public 以允许从 Base 类访问它。我希望方法 void impl() 再次成为私有的。可以做到吗?
更新:我不想写
friend class Base<Derived>;
Run Code Online (Sandbox Code Playgroud)
在 Derived 类中,因为它允许 Base 访问 Derived 的所有成员。
我正在关注这个博客,并试图将动态多态性代码替换为使用std::variantand std::visit。但我无法让std::variant+std::visit比 virtual struct impl 更好地工作。速度慢了大约1.3-1.5 倍!(GCC 10.3 -O3 C++17)
用例如下。假设我们正在比较两个表的第 i 行和第 j 行。表可以具有异构类型的列。假设我们可以访问列缓冲区。我正在做的是测试,
def IndexEqual(Table:A, Table:B, int:i, int:j):
for c in range(A.num_cols):
if not A.column(c)[i] == B.column(c)[j]:
return False
return True
Run Code Online (Sandbox Code Playgroud)
对于动态多态性,我有以下内容int和float
struct Comp{
virtual bool comp(size_t i, size_t j) const = 0;
};
struct CompI: public Comp {
CompI(const int *data_1, const int *data_2) : data1(data_1), data2(data_2) {}
const int *data1, *data2;
bool …Run Code Online (Sandbox Code Playgroud) 我想知道如果我从不从基类调用函数(即虚拟调度),使用 CRTP 是否比虚拟函数多态性有任何好处?
这是示例代码。反汇编可以在https://godbolt.org/z/WYKaG5bbG找到。
struct Mixin {
virtual void work() = 0;
};
template <typename T>
struct CRTPMixin {
void call_work() {
static_cast<T*>(this)->work();
}
};
struct Parent {};
struct Child : Parent, Mixin, CRTPMixin<Child> {
int i = 0;
void work() override {
i ++;
}
};
Child child;
Mixin& mixin = child;
int main() {
child.work();
mixin.work();
child.call_work();
}
Run Code Online (Sandbox Code Playgroud)
work我发现如果我从接口child或通过接口调用虚函数CRTPMixin,反汇编代码是相同的,只有 static call。如果我调用该函数,Mixin& mixin = child就会发生虚拟调度,并且会为此操作生成更多指令。
我的问题是,如果我正在设计接口/混合类型结构,我只会使用派生类而不是基类来调用它,是否有任何情况 CRTP 会比虚拟函数方法受益更多?
谢谢!
尝试在没有基类和虚拟调用的情况下获取编译时方法和对象选择.
情况如下:
struct A {
void f1()const { cout << "A::f1" << endl;}
void f2()const { cout << "A::f2" << endl;}
};
struct B {
void f1()const { cout << "B::f1" << endl;}
void f2()const { cout << "B::f2" << endl;}
};
class Holder {
A* _a = nullptr;
B* _b = nullptr;
public:
Holder(A* a): _a(a) {}
Holder(B* b): _b(b) {}
void f1()const {
if(_a) _a->f1();
else if(_b) _b->f1();
}
void f2()const {
if(_a) _a->f2();
else if(_b) _b->f2();
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试这样做,但我没有成功.
abstract class Animal
{
abstract static function getName();
static function sayName() { echo self::getName(); }
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我正在考虑为我的应用程序使用奇怪的重复模板模式.但是,我希望这些类能够在用户定义的类型上运行.我想了解是否可以创建类似于下面所示的结构:
template <class T_leaftype>
class BaseTrajectoryPoint {
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint> {
private:
MyType A;
};
Run Code Online (Sandbox Code Playgroud)
上面的代码无法编译,出现以下错误:
模板参数列表中参数1的类型/值不匹配'模板类BaseTrajectoryPoint'
有没有其他方法来解决问题?我想使用静态多态,但我更喜欢在基类中定义所有可能的方法.
我坚持使用这种模式,因为我创建的只有一个派生类得到实例化.用g ++和MSVS检查.具体来说,只创建了我定义的第一个派生类.编译器不会发出任何类型的警告.完整代码如下.
#include <iostream>
static int nodes = 0;
class TreeNode {
private:
int m_id;
public:
TreeNode() :
m_id(++nodes)
{}
TreeNode(int id) :
m_id(id)
{
++nodes;
}
TreeNode* left;
TreeNode* right;
int getId() const {
return m_id;
}
};
template<typename T>
//typename std::enable_if<std::is_base_of<TreeParser, T>::value>::type
class TreeParser {
protected:
TreeParser() {
++parsers;
}
public:
static uint32_t parsers;
void preorderTraversal(TreeNode* node) {
if (node != nullptr) {
processNode(node);
preorderTraversal(node->left);
preorderTraversal(node->right);
}
}
virtual ~TreeParser() = default;
void processNode(TreeNode* node) { // 2, …Run Code Online (Sandbox Code Playgroud) c++ ×8
polymorphism ×5
templates ×4
crtp ×3
inheritance ×2
oop ×2
abstract ×1
c++14 ×1
c++17 ×1
haskell ×1
list ×1
macros ×1
php ×1
std-variant ×1
types ×1