Thread overview
Why does this extremely simple operation not work?
Feb 12, 2013
William
Feb 12, 2013
monarch_dodra
Feb 12, 2013
Jonathan M Davis
Feb 12, 2013
d coder
Feb 13, 2013
Ali Çehreli
February 12, 2013
This is an absurdly noobish question, but here goes.  I'm learning D (I'm already reasonably comfortable with C and Objective-C, so compiled languages are not new to me), and I can't figure out why this super simple operation doesn't work.

I have a parent and a child class, and while implicit casting from child to parent works (function which takes parent will accept instance of child), it does not work with pointers (and yes, I understand that because objects are reference types a MyObject* is really a pointer to a pointer since a MyObject is a pointer).  A function that takes a Parent* as an argument will not accept &myChild in its place without an explicit cast(Parent*)&myChild.

I feel like there's some fundamental property of the D implementation that I'm not getting.  I was under the impression an subtype's instance could *always always always* be put in place of an instance of the super type.  Why are pointers an exception?

class Parent {}
class Child : Parent {}

void myFunc(Parent* obj) {
	writeln("got ", obj);
}

void main() {
	Child myChild = new Child();
	myFunc(&myChild);
}

referenceTest.d(11): Error: function referenceTest.myFunc (Parent* obj) is not callable using argument types (Child*)
referenceTest.d(11): Error: cannot implicitly convert expression (& myChild) of type Child* to Parent*
February 12, 2013
On Tuesday, 12 February 2013 at 16:58:24 UTC, William wrote:
> This is an absurdly noobish question, but here goes.  I'm learning D (I'm already reasonably comfortable with C and Objective-C, so compiled languages are not new to me), and I can't figure out why this super simple operation doesn't work.
>
> I have a parent and a child class, and while implicit casting from child to parent works (function which takes parent will accept instance of child), it does not work with pointers (and yes, I understand that because objects are reference types a MyObject* is really a pointer to a pointer since a MyObject is a pointer).  A function that takes a Parent* as an argument will not accept &myChild in its place without an explicit cast(Parent*)&myChild.
>
> I feel like there's some fundamental property of the D implementation that I'm not getting.  I was under the impression an subtype's instance could *always always always* be put in place of an instance of the super type.  Why are pointers an exception?
>
> class Parent {}
> class Child : Parent {}
>
> void myFunc(Parent* obj) {
> 	writeln("got ", obj);
> }
>
> void main() {
> 	Child myChild = new Child();
> 	myFunc(&myChild);
> }
>
> referenceTest.d(11): Error: function referenceTest.myFunc (Parent* obj) is not callable using argument types (Child*)
> referenceTest.d(11): Error: cannot implicitly convert expression (& myChild) of type Child* to Parent*

You'd get the same behavior problem in C++. Where you can't pass a "Child**" when asking for a "Parent**". Long story short, if you could, you'd be able to place a parent instance inside a child instance, and mess everything up:

void myFunc(Parent* obj)
{
	static Parent par;
	if(!par) par = new Parent();
	obj = ∥
}
void main() {
	Child myChild = new Child();
	myFunc(&myChild);
	//Here, myChild is a reference to a Parent => Type system broken
}
February 12, 2013
In D, class objects are implicitly pointers. So try the following code.

class Parent {}
class Child : Parent {}

void myFunc(Parent obj) {
  import std.stdio;
  writeln("got ", obj);
}

void main() {
  Child myChild = new Child();
  myFunc(myChild);
}
February 12, 2013
On Tuesday, February 12, 2013 18:04:18 monarch_dodra wrote:
> You'd get the same behavior problem in C++. Where you can't pass a "Child**" when asking for a "Parent**". Long story short, if you could, you'd be able to place a parent instance inside a child instance, and mess everything up:
> 
> void myFunc(Parent* obj)
> {
> static Parent par;
> if(!par) par = new Parent();
> obj = ∥
> }
> void main() {
> Child myChild = new Child();
> myFunc(&myChild);
> //Here, myChild is a reference to a Parent => Type system broken
> }

Yeah. It's good to keep in mind that whenever you see a class referred to as a type, it's really referring to a reference to a class object, _not_ the class object itself, which is why &obj doesn't point to the class object but to its reference, and the reference doens't have a parent or child relationship with any classes - just the class itself has that.

- Jonathan M Davis
February 13, 2013
On 02/12/2013 08:58 AM, William wrote:

> I'm learning D

There is also the D.learn newsgroup.

Ali