也许C和Java人员可以帮我定义这个我要解释的问题 . 关于如何表示实现动态标识符的三个主要分支的类的构造函数,我在Ada(你不需要知道它,我只是对这个概念感兴趣)有一个问题:
-
纯数值(int,float,String,等等)
-
列表/堆栈项目
-
C中的东西可能是一个线程(在Ada中我们有一个更广泛的概念,与任务相关,但我们可以将一个简单的任务概念作为一个线程,所以这个概念也适用)
我要调用这个类 Par_Class
,并且是任何构造的对象调用 Par_Obj
. 因此,当创建对象 Par_Obj
时(因此,数值初始化,列表/堆栈分配了其他列表/堆栈或为空并且保留了线程执行的内存范围),OS自动开始执行新的线程与我的主应用程序并行(现在他们争夺系统资源) . 但是为了简化示例,让's suppose I' d有一个带有整数的类和一个指向字符串的指针 .
例如,在C中,我可以编码(如果我做错了,请纠正我)
class Par_Class {
public:
Par_Class (int aValue, const std::string & aName);
private:
int theValue;
std::string theName;
};
构造函数可以实现为
Par_Class::Par_Class (int aValue, const std::string & aName)
: theValue(aValue)
, theName(aName)
{
}
最后我们可以实例化这个类
Par_Class Par_Obj (23, "My object is this");
并确保此构造方法属于Par_Class类,而不属于任何其他类 .
同样,在Java中,我们可以编码
public class Par_Class {
private int theValue;
private String theName;
public Par_Class (int aValue, String aName){
theValue = aValue;
theName = aName;
}
};
我们可以使用实例化对象
Par_Class Par_Obj = new Par_Class (23, "My object is this");
(如果我错了,请再次纠正我) . 同样, Par_Class
构造函数是类 Par_Class
的方法 .
在Ada 2005中,这个类可以编码为
--par_pkg.ads
package Par_Pkg is
type Par_Class is tagged private;
type Par_Class_Ptr is access all Par_Class;
type Integer_Ptr is access Integer;
function Construct
(P : access Par_Class; aValue : Integer; aName : Integer_Ptr)
return Par_Class_Ptr;
private
type Par_Class is tagged
record
theValue : Integer;
theName : Integer_Ptr;
end record;
end Par_Pkg;
-- par_pkg.adb
package body Par_Pkg is
function Construct
(P : access Par_Class; aValue : Integer; aName : Integer_Ptr)
return Par_Class_Ptr is
pragma Unreferenced (P);
P_Ptr : constant Par_Class_Ptr := new Par_Class;
begin
P_Ptr.theValue := aValue;
P_Ptr.theName := aName;
return P_Ptr;
end Construct;
end Par_Pkg;
并且用户可以打电话
with Par_Pkg; use Par_Pkg;
procedure Par_Main is
Par_Obj : Par_Class_Ptr;
Int_Obj : Integer_Ptr;
begin
Int_Obj := new Integer;
Int_Obj.all := 12; -- don't worry about been string or integer
Par_Obj := Par_Obj.Construct
(aValue => 23,
aName => Int_Obj);
end Par_Main;
这就是问题所在 . 编译器告诉我,我无法在 Par_Obj := Par_Obj.Construct
中使用方法Construct,因为我的对象是null . 但是它想要使用这种方法,因为它远离架构 . 你能帮我把这个问题告诉我的Ada朋友,这样他们可以帮我在Ada中实现吗?我想我在一般概念术语中解释这个问题有点困难 . 谢谢 .
Answer
@paercebal给了我我认为可以实现我的目标:
- "Is there a way to have a "静态" function declared inside Par_Class?"和"is there a way to have an non-member function declared friend of Par_Class?"
我可以完成它“有没有办法在标记类型中声明一个”静态“函数?另外,声明类的包可以充当朋友还是静态函数?”
Update
根据@SimonWright和comp.lang.ada论坛的一些人的建议,为什么实现它有一些更好的理由:
function Construct (aValue: Integer; aName: Integer)
return Par_Class is
begin
return (theValue => aValue,
theName => aName);
end Construct;
所以我问:在这种情况下,函数Construct会表现为C静态函数(或者可能是朋友吗?)?
德米特里卡扎科夫回答说:
这取决于你的意思 . 在Ada中:没有隐藏的参数,操作可以在任何参数和/或结果的组合中调度(虚拟) . 但是操作不能在多种类型中调度(没有多次调度) . 调度参数的所有标签必须相同(没有多方法) . 没有静态或朋友操作,因为可见性规则基于包 . 上面的函数Construct是一个原始操作,它不是构造函数 . Ada中的构造函数是隐含的,它们由组件的构造(以未指定的顺序,递归地)组成;如果类型是Ada.Finalization的后代,则调用Initialize . [Limited_]受控制 . (不会调用重写的Initialize主体!即Ada构造函数不会遍历派生路径 . 简而言之,聚合是安全的,派生不是;启动所有任务组件 . (注意,调用Initialize时任务不会运行!)析构函数在相反的顺序:tasks - Finalize - components .
我猜它会回应 . 谢谢大家
3 回答
关于Ada构造函数?
由于我不知道Ada语言的哲学,局限性和优势,因此很难解释这个概念 . 仍然,猜测Ada中没有构造函数 .
A(非朋友?)非会员功能?
这不是你想要的解决方案我想:
具有
Par_Class
的Initialize
成员函数,用于设置Par_Class
的私有数据有
Par_Class_Constructor
非成员函数调用Initialize函数但是这个解决方案并不令人满意,因为它会将
Initialize
暴露为公共方法,这是一个 breach of encapsulation (任何人都可以在任何时刻调用该方法,这几乎与使所有数据公开一样愚蠢) .静态成员函数?
你想要做的是用 one function call, without breaching encapsulation 分配和初始化你的代码 .
You feel (rightly) this function should be part of Par_Class interface ,因此,你想要 declare it inside the Par_Class' declaration (这会产生有趣的副作用,即允许它访问
Par_Class
私有成员变量)在Java或C中,禁止构造函数,这可以通过使用静态方法(即类的方法)而不是实例的方法来解决 . 此方法是
static
,因此无法访问this
,这意味着您可以不需要Par_Class
的实例就可以调用它 .那么,你对Ada朋友的问题可能是: is there a way to have a "static" function declared inside Par_Class?
A(朋友?)非会员功能?
另一种具有相似效果的方法(如果不是类似的语法糖)将是一个非成员函数来做这个技巧 . 在C中,你会有类似的东西:
Par_Class_Constructor
,这是一个函数,返回指向Par_Class类型的struct
的指针 .在C中,您可以使用与Java相同的技巧,或者使用与C相同的技巧 . 在最后一种情况下,
Par_Class_Constructor
将被声明Par_Class
类Par_Class
以访问其私有数据,或者可以调用初始化成员方法访问该私人数据 .这样, you can still allocate and initialize your object with one function,and still protect the encapsulation of your class (因为此方法返回一个新对象,而不是像上面描述的令人不满意的
Initialize
方法那样修改它)所以,如果你有一个非成员函数是好的,另一种可能性是: is there a way to have an non-member function declared friend of Par_Class?
编辑
注意:我之前的,主题外答案......我真的应该去睡觉了......
我不知道阿达,但阅读你的代码:
我看到Int_Obj已经分配了
new Integer
语句 .你不需要以同样的方式分配Par_Obj吗?
像(我从你的整数初始化代码推断):
???
Par_Class (int aValue, const char *aName)
是非常特殊的C构造函数语法;当使用时,编译器会生成一个新的内存空白区域(如果在堆栈上有new
则调用malloc()
,否则构造函数会填充它) .这跟不一样
这需要有一个以前的
Par_Class
实例,就像有一个C成员函数如果使用未初始化的
Par_Class *
调用,它将以与当前Ada代码相同的方式失败 .我认为最接近(Ada 2012)相当于构造函数
或者,对于Ada 95/2005并且最接近您现有的计划:
@paercebal提到你需要一个静态成员函数,这是正确的; C构造函数是我认为这个的语法糖 . 在Ada中,范围确定是在包级别完成的,因此
function Construct
- 在同一个包的公共部分中声明并返回Par_Class_Ptr
- 与Par_Class
无关紧要(在架构上) .注意变化;构造函数现在返回正确的[指针]类型,并且永远不允许它为null .
此外,对象的构造被移动到初始化部分而不是主体 . 所以这确保了对象[-pointer]永远不会为空 .