digitalmars.D - Linker errors with Interfaces
- Andrej Mitrovic (90/90) Aug 10 2010 Excerpt from TDPL, p213-214:
- Igor Lesik (110/110) Aug 10 2010 I think, it is not linker error at all.
- Andrej Mitrovic (4/118) Aug 11 2010 Private does not prevent overriding, final prevents overriding. Private
- Michel Fortin (13/16) Aug 11 2010 The D spec says private member functions are not virtual. Not that I
- Adrian Matoga (4/10) Aug 11 2010 I reported this as a bug a few days ago:
- Andrej Mitrovic (2/13) Aug 11 2010
- Andrej Mitrovic (9/27) Aug 11 2010 Reading from TPDL again, the "final void thereandback()" method in the
Excerpt from TDPL, p213-214: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override private void transmogrify() { // get in the box } override private void untransmogrify() { // get out of the box } } void play() { writeln("just playing"); } void aDayInLife(Transmogrifier device, string mood) { if (mood == "play") { device.transmogrify(); play(); writeln(typeid(device)); device.untransmogrify(); } else if (mood == "experiment") { device.thereAndBack(); } } import std.stdio; void main() { aDayInLife(new CardboardBox, "play"); } Calling device.transmogrify() and device.untransmogrify() should not even be allowed to compile. I can comment these out, but the linker will still fail when there's a call to device.thereAndBack(); device is an object that inherits from interface Transmogrifier, and "thereAndBack()" is a public method of the interface, so I'm not sure whats wrong with that call. I get these in both cases: output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZv One more thing, here's a class that inherits from the same interface, but tries to make the overriden methods non-private by mistake: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override void transmogrify() { // get in the box } override void untransmogrify() { // get out of the box } } I get these errors: interface_test.d(23): Error: function interface_test.CardboardBox.transmogrify does not override any function interface_test.d(28): Error: function interface_test.CardboardBox.untransmogrify does not override any function The book has nice plausible error message alternatives: // Error: Cannot change protection of transmogrify from private to public // Error: Cannot change protection of untransmogrify from private to public I'd prefer if DMD put out those kinds of error messages in this case (or something similar).
Aug 10 2010
I think, it is not linker error at all. "private" in Transmogrifier prevents overriding; and since those 2 functions are not defined but still in use (vtbl) linker does not find them and complains. Replace "private" with protected (in CardboardBox also) and it all works. compiler should say that the functions are not overrided; I am sure a bug report already filed for this issue Igor From: Andrej Mitrovic Subject: Linker errors with Interfaces Excerpt from TDPL, p213-214: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override private void transmogrify() { // get in the box } override private void untransmogrify() { // get out of the box } } void play() { writeln("just playing"); } void aDayInLife(Transmogrifier device, string mood) { if (mood == "play") { device.transmogrify(); play(); writeln(typeid(device)); device.untransmogrify(); } else if (mood == "experiment") { device.thereAndBack(); } } import std.stdio; void main() { aDayInLife(new CardboardBox, "play"); } Calling device.transmogrify() and device.untransmogrify() should not even be allowed to compile. I can comment these out, but the linker will still fail when there's a call to device.thereAndBack(); device is an object that inherits from interface Transmogrifier, and "thereAndBack()" is a public method of the interface, so I'm not sure whats wrong with that call. I get these in both cases: output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZv One more thing, here's a class that inherits from the same interface, but tries to make the overriden methods non-private by mistake: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override void transmogrify() { // get in the box } override void untransmogrify() { // get out of the box } } I get these errors: interface_test.d(23): Error: function interface_test.CardboardBox.transmogrify does not override any function interface_test.d(28): Error: function interface_test.CardboardBox.untransmogrify does not override any function The book has nice plausible error message alternatives: // Error: Cannot change protection of transmogrify from private to public // Error: Cannot change protection of untransmogrify from private to public I'd prefer if DMD put out those kinds of error messages in this case (or something similar).
Aug 10 2010
Private does not prevent overriding, final prevents overriding. Private prevents the methods from being explicitly called from either user code or any derived classes. On Wed, Aug 11, 2010 at 8:08 AM, Igor Lesik <curoles yahoo.com> wrote:I think, it is not linker error at all. "private" in Transmogrifier prevents overriding; and since those 2 functions are not defined but still in use (vtbl) linker does not find them and complains. Replace "private" with protected (in CardboardBox also) and it all works. compiler should say that the functions are not overrided; I am sure a bug report already filed for this issue Igor From: Andrej Mitrovic Subject: Linker errors with Interfaces Excerpt from TDPL, p213-214: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override private void transmogrify() { // get in the box } override private void untransmogrify() { // get out of the box } } void play() { writeln("just playing"); } void aDayInLife(Transmogrifier device, string mood) { if (mood == "play") { device.transmogrify(); play(); writeln(typeid(device)); device.untransmogrify(); } else if (mood == "experiment") { device.thereAndBack(); } } import std.stdio; void main() { aDayInLife(new CardboardBox, "play"); } Calling device.transmogrify() and device.untransmogrify() should not even be allowed to compile. I can comment these out, but the linker will still fail when there's a call to device.thereAndBack(); device is an object that inherits from interface Transmogrifier, and "thereAndBack()" is a public method of the interface, so I'm not sure whats wrong with that call. I get these in both cases: output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZv One more thing, here's a class that inherits from the same interface, but tries to make the overriden methods non-private by mistake: interface Transmogrifier { // client interface final void thereAndBack() { transmogrify(); untransmogrify(); } // implementation interface private: void transmogrify(); void untransmogrify(); } class CardboardBox : Transmogrifier { override void transmogrify() { // get in the box } override void untransmogrify() { // get out of the box } } I get these errors: interface_test.d(23): Error: function interface_test.CardboardBox.transmogrify does not override any function interface_test.d(28): Error: function interface_test.CardboardBox.untransmogrify does not override any function The book has nice plausible error message alternatives: // Error: Cannot change protection of transmogrify from private to public // Error: Cannot change protection of untransmogrify from private to public I'd prefer if DMD put out those kinds of error messages in this case (or something similar).
Aug 11 2010
On 2010-08-11 08:33:00 -0400, Andrej Mitrovic <andrej.mitrovich gmail.com> said:Private does not prevent overriding, final prevents overriding. Private prevents the methods from being explicitly called from either user code or any derived classes.The D spec says private member functions are not virtual. Not that I agree with it, but it's like this. "All non-static non-private non-template member functions are virtual." <http://www.digitalmars.com/d/2.0/function.html> The worst part of it is that changing a function from private to public, or the reverse, is a breaking ABI change because it affects the vtable. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Aug 11 2010
I get these in both cases: output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZvI reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian
Aug 11 2010
DMD and TDPL will get in sync one day, I hope. 2010/8/11 Adrian Matoga <epi atari8.info>I get these in both cases:output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZvI reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian
Aug 11 2010
Reading from TPDL again, the "final void thereandback()" method in the interface is what the user code is expected to call. That method calls two private methods. But it will call the two private methods in the interface, not the two from the derived class (since private methods are not virtual). E.g. calling thereandback() explicitly from a derived object will call the interface method, since it is final, which then calls the private methods from the interface. It's like a dead-end here. On Wed, Aug 11, 2010 at 3:23 PM, Andrej Mitrovic <andrej.mitrovich gmail.comwrote:DMD and TDPL will get in sync one day, I hope. 2010/8/11 Adrian Matoga <epi atari8.info> I get these in both cases:output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier12transmogrifyMFZv output\interface_test.obj(interface_test) Error 42: Symbol Undefined _D14interface_test14Transmogrifier14untransmogrifyMFZvI reported this as a bug a few days ago: http://d.puremagic.com/issues/show_bug.cgi?id=4542 I like the NVI idiom and hope this will finally work in future releases. Adrian
Aug 11 2010