What is the prefered method to initialize the parent object?

General FreeBASIC programming questions.
Tourist Trap
Posts: 2644
Joined: Jun 02, 2015 16:24

What is the prefered method to initialize the parent object?

Postby Tourist Trap » Mar 16, 2019 13:35

Hi,

I have a parent object with no constructor here. But of course in some cases there could be some need for a constructor. Anyway my question is simply a question of efficiency about how to intitialize the parent object of an inherited object (child contains parent so this part of the child has to be initialized somehow).
I have 4 versions here below that for me looks absolutely the same. Maybe however some of this is faster and so on. Maybe there is even another way like the use of the operator LET, I don't know.
Any opinion?

Code: Select all


type PARENT
    'declare constructor()
    as integer  dummyparentvariable
end type
'constructor PARENT()
    '
'end constructor

type CHILD extends PARENT
    declare constructor()
    declare constructor(as PARENT)
    declare constructor(as PARENT ptr)
        as integer  dummychildvariable
end type
constructor CHILD()
    'BASE()
    '
end constructor
constructor CHILD(byref P as PARENT)
    cast(PARENT, THIS) = P
    '
end constructor
constructor CHILD(byval Pptr as PARENT ptr)
    *cptr(PARENT ptr, @THIS) = *Pptr
    '
end constructor


'test
dim as PARENT   p
P.dummyparentvariable = 999

dim as CHILD    c = CHILD(p)
c.dummychildvariable = 7
? "par0"; c.dummyparentvariable
? "chi0"; ; c.dummychildvariable

dim as CHILD    c1 = CHILD(@p)
c1.dummychildvariable = 71
? "par1"; c1.dummyparentvariable
? "chi1";  c1.dummychildvariable

dim as CHILD    c2 = CHILD(type<PARENT>(888))
c2.dummychildvariable = 72
? "par2"; c2.dummyparentvariable
? "chi2";  c2.dummychildvariable

dim as CHILD    c3 = CHILD(@type<PARENT>(-888))
c3.dummychildvariable = 73
? "par3"; c3.dummyparentvariable
? "chi3"; c3.dummychildvariable


sleep


Thank you
fxm
Posts: 8763
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What is the prefered method to initialize the parent object?

Postby fxm » Mar 16, 2019 15:01

If I reword your question (clearer for me):
How to construct / initialize a CHILD instance so that all its inherited data are equal to that of an already existing PARENT instance?

My preferring is rather your first proposal (using the following constructor):

Code: Select all

constructor CHILD(byref P as PARENT)
    cast(PARENT, THIS) = P
    '
end constructor

or simply (without explicit constructor):

Code: Select all

dim as CHILD c4
cast(PARENT, c4) = p
Tourist Trap
Posts: 2644
Joined: Jun 02, 2015 16:24

Re: What is the prefered method to initialize the parent object?

Postby Tourist Trap » Mar 16, 2019 15:21

fxm wrote:My preferring is rather your first proposal (using the following constructor):

Code: Select all

constructor CHILD(byref P as PARENT)
    cast(PARENT, THIS) = P
    '
end constructor

or simply (without explicit constructor):

Code: Select all

dim as CHILD c4
cast(PARENT, c4) = p

Hi fxm,

thanks for answering!
fxm
Posts: 8763
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What is the prefered method to initialize the parent object?

Postby fxm » Mar 17, 2019 14:14

- Defining an explicit copy(from PARENT datatype)-constructor in CHILD Type without defining also an explicit copy(from CHILD datatype)-constructor is risky because this explicit definition remove the definition of an implicit copy(from CHILD datatype)-construction by compiler.
So any CHILD instance used in a copy-construction will be in fact sliced (by copying only data declared in the PARENT Type).

- A similar behavior does not occurs with the let operator.
Defining an explicit copy(from PARENT datatype)-assignment operator in CHILD Type without defining also an explicit copy(from CHILD datatype)-assignment operator is not risky because this explicit definition does not remove the definition of an implicit copy(from CHILD datatype)-assignment operation by compiler.

I find the difference between these two behaviors (copy-construction versus copy-assignment operation, both from a BASE instance parameter) not logical at all.
Is it wanted?


Example:

Code: Select all

type PARENT
    as integer  dummyparentvariable
end type

type CHILD extends PARENT
    declare constructor()
    declare constructor(byref as PARENT)
    declare operator let(byref as PARENT)
    as integer  dummychildvariable
end type
constructor CHILD()
end constructor
constructor CHILD(byref p as PARENT)
    THIS.dummyparentvariable = p.dummyparentvariable
end constructor
operator CHILD.let(byref p as PARENT)
    THIS.dummyparentvariable = p.dummyparentvariable
end operator


'test
dim as CHILD c1
c1.dummyparentvariable = 1
c1.dummychildvariable = 2
print c1.dummyparentvariable, c1.dummychildvariable

dim as CHILD c2 = c1  '' CHILD instance is sliced
print c2.dummyparentvariable, c2.dummychildvariable

dim as CHILD c3
c3 = c1  '' CHILD instance is not sliced
print c3.dummyparentvariable, c3.dummychildvariable

sleep

Code: Select all

 1             2
 1             0
 1             2


[edit]
Note:
If a constant CHILD instance is used for copy-construction, the implicit copy-construction of the compiler is correctly selected and executed (the data in the CHILD type are also initialized):

Code: Select all

dim as CHILD c2 = cast(const CHILD, c1)  '' CHILD instance is no sliced
At the cons, use such a constant Child instance is not necessary to obtain a correct copy-assignment operation.
Finally:
If the explicit copy-constructor is now declared using a constant PARENT parameter, an incomplete copy is again obtained (in all cases):

Code: Select all

    declare constructor(byref as const PARENT)
In all cases, no impact on copy-assignment if the explicit copy-assignment operator is also declared using a constant PARENT parameter:

Code: Select all

    declare operator let(byref as Const PARENT)

It is mainly on the above inconsistency between copy-construction and copy-assignment behaviors that I question!
Last edited by fxm on Mar 19, 2019 9:20, edited 4 times in total.
fxm
Posts: 8763
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What is the prefered method to initialize the parent object?

Postby fxm » Mar 18, 2019 14:22

If the PARENT type has now a default constructor (or data field initializer), an incomplete copy is also obtained from a copy assignment operation:

Code: Select all

type PARENT
    declare constructor()
    as integer  dummyparentvariable
end type
constructor PARENT()
end constructor

type CHILD extends PARENT
    declare constructor()
    declare constructor(byref as PARENT)
    declare operator let(byref as PARENT)
    as integer  dummychildvariable
end type
constructor CHILD()
end constructor
constructor CHILD(byref p as PARENT)
    THIS.dummyparentvariable = p.dummyparentvariable
end constructor
operator CHILD.let(byref p as PARENT)
    THIS.dummyparentvariable = p.dummyparentvariable
end operator



'test
dim as CHILD c1
c1.dummyparentvariable = 1
c1.dummychildvariable = 2
print c1.dummyparentvariable, c1.dummychildvariable

dim as CHILD c2 = c1  '' CHILD instance is sliced
print c2.dummyparentvariable, c2.dummychildvariable

dim as CHILD c3
c3 = c1  '' CHILD instance is also sliced
print c3.dummyparentvariable, c3.dummychildvariable

sleep

Code: Select all

 1             2
 1             0
 1             0
Last edited by fxm on Mar 19, 2019 9:12, edited 2 times in total.
fxm
Posts: 8763
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: What is the prefered method to initialize the parent object?

Postby fxm » Mar 19, 2019 8:23

[edit]
Added a previous post


From the two previous posts and other already known rules as 'golden rules', a 'maximizing rule' could be proposed to always obtain a safe operation whatever the configuration:
  • If the user needs to explicitly defines any form of constructor procedure (including any form of copy constructor) or any form of let-operator procedure or a destructor procedure,
    => then it is strongly recommended to define together the default constructor and the standard copy constructor and the standard let operator and the destructor.
    (these 4 explicit procedures are explicitly defined to always overload correctly the corresponding implicit operations from compiler)

Return to “General”

Who is online

Users browsing this forum: Baidu [Spider], MLambert and 2 guests