类属性的 C++ 等价于 Matlab Abstract
Posted
技术标签:
【中文标题】类属性的 C++ 等价于 Matlab Abstract【英文标题】:C++ equivalent of Matlab Abstract for class properties 【发布时间】:2013-01-16 13:14:47 【问题描述】:短版: 考虑以下伪代码:
class Foo
private:
abstract type myVar;
// This class is abstract
您将如何在标准 C++ 中实现此行为?
加长版: 我必须将大量面向 Obj 的代码从 Matlab 移植到 C++。 请注意,我是世界上使用 Matlab 经验最少的人,自 2007 年以来我就不再使用 C++。
我在这个主题上搜索了很多,但我找不到我的问题的正确答案。 所以我在这里:)
假设你有这个 matlab 类:
classdef Foo < handle
properties (Abstract, Dependent)
A
end
properties
B
end
methods (Abstract)
computeA()
end
methods (Access = protected)
function obj = Foo(bar)
obj.B = Matlab.BlaBlaBla(bar)
end
end
这个类(我想)不能“直接”分配,因为它的构造函数是受保护的。 属性“A”也是抽象的(暂时忽略也是依赖的事实)。 MathWorks 告诉我们,这意味着:
具体的子类必须重新定义抽象属性 抽象属性,并且必须为 SetAccess 和 GetAccess 属性与抽象超类中使用的属性相同。 抽象属性无法定义 set 或 get 访问方法(请参阅 属性访问方法)并且不能指定初始值。这 定义具体属性的子类可以创建 set 或 get 访问方法并指定初始值。那么你将如何正确地在 C++ 中翻译这种行为呢? 如果我按照以下方式进行操作是否正确? (我的意思是说这不是一个糟糕的设计实践)
class Foo
private:
type A;
type B;
protected:
virtual void computeA() = 0;
Foo(type bar) this.B = SomeFoo(bar);
我的想法(我可能错了)是,如果我这样做,就必须这样做
class Subclass: Foo
protected:
void computeA()...
public:
type A() computeA(); return A; //This is A getter that grants Dependent behavior
否则会在编译时出错。
我错了吗?有更好的方法吗? 也是翻译 Dependent 关键字的正确方法吗?
【问题讨论】:
至少根据您的描述,在我看来,Matlab 属性已经够混乱了(如果您愿意,可以将其读作“对于 C++ 而言足够陌生”)任何 翻译成 C++ 将做以下两件事之一:要么大量更改代码,要么最终变成相当糟糕(或至少很奇怪)的 C++。 抽象关键字定义取自 MathWorks 网站。此外,我认为通过使用 Dependent 关键字获得的行为在 C++ 中并不奇怪。它允许您仅在需要时才计算属性 A,并且它允许您在使用它时始终更新它。还要考虑到我可能误解了 Dependent 对 matlab 的含义 :) 注意Subclass不能访问Foo的私有成员A。 让我举一个例子来说明我的意思。 C++ 使得在需要时计算值变得容易——这没有问题。在基类中声明这将在所有派生类中发生——好吧,对不起,但我不知道有什么方法可以做到这一点。也就是说,我认为没有理由这样做——在 C++ 中,告诉用户他们将更新的值大致相当于告诉某人你给他们的水是湿的。除非您另有说明,否则每个人都会认为是这种情况。 好的,所以 Dependent 是一个简单的可复制行为。摘要呢? 【参考方案1】:首先,我认为重要的是要问:一个类的公共接口是什么(它的职责是什么,它如何与其他人交互)?
从您的 Matlab 代码中,答案是:该类定义了属性 A 和 B 以及方法 computeA。根据我对 Dependent 属性的理解,我怀疑 computeA() 应该是公开的(参见Matlab docs)。如果您的其余代码需要这个,当然您可以将其公开,但我会尽量减少可访问性。
现在 C++ 中不存在属性的概念。 Matlab 的有趣之处在于基类决定是否存在 A.get、A.set 或两者以及可访问性。我不知道这背后的原因,但在我看来这似乎没有太大意义。在 C++ 中,我会将属性转换为获取/设置方法。请参阅this question 以了解在 C++ 中实现这些的讨论。根据您的选择,您可以将非依赖属性实现为成员对象或 get/set 方法。
一旦您定义了方法的公共接口,我就会尝试开始考虑如何实现它。请注意,Matlab 和 C++ 的内存管理是不同的(Matlab 使用 Copy on Write 并关心内存管理,这在纯 C++ 中不存在)。此外,在(慢速面向对象的)Matlab 代码中可能需要缓存值(如使用 computeA 和相关属性所做的那样),但在 C++ 中则不一定。为了避免过早的优化,为什么不这样做:
class Foo
public:
ClassB B;
virtual ClassA getA() = 0;
//define a setA()=0 if you need it here
protected:
//I wouldn't force subclasses to have the "caching" of dependent properties, so no virtual void computeA() = 0;
Foo(ClassBar const& bar) this.B = ClassB(bar); /*Note that SomeFoo cannot be assigned to B*/
class Subclass: public Foo
private:
ClassA A;
public:
ClassA getA() ClassA A; /*compute A*/ return A;
如果你遇到A的计算太慢,你仍然可以在子类中“本地缓存A”:
class Subclass: public Foo
private:
ClassA A;
public:
ClassA getA() /*compute A if required*/ return A;
如果你真的想将 A 存储在 Foo 中,我宁愿将它实现为
class Foo
private:
ClassA A;
public:
ClassB B;
ClassA getA() if (!A.initialized) A=computeA(); return A; ;
protected:
virtual ClassA computeA() = 0;
Foo(ClassBar const& bar) this.B = ClassB(bar); /*Note that SomeFoo cannot be assigned to B*/
class Subclass: public Foo
protected:
virtual ClassA computeA() ...
并且不要忘记始终考虑您是否真的想通过(const)引用或值传递......
【讨论】:
我已经仔细阅读了这篇文章,您的建议似乎都很好,澄清了我的大部分疑问。谢谢你的时间:)以上是关于类属性的 C++ 等价于 Matlab Abstract的主要内容,如果未能解决你的问题,请参考以下文章