Thread: Object not showing Polymorphic Behaviour

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    219

    Object not showing Polymorphic Behaviour

    I've a Class called Layout which is the parent class of MyLayout
    e.g. MyLayout extends Layout.
    Now another Class App takes Layout& argument on one of its constructor.
    App Class have a member variable called layout on which an instance of Layout Class exists.
    which is meant to be optionally instantiable from constructor.
    App Class have an exec() method that calls layout.fnc()
    Layout's fnc() is virtual

    Now the problem is I should be able to do App app(MyLayout) as well as App(Layout)
    as MyLayout is a Child class of Layout Class.

    The Code is being Compiled if I pass a MyLayout Class in constructor's argument.
    but It is calling Layout::fnc() instead of MyLayout::fnc()

    -------------- All My codes are Attached ------------------

    layout.h
    Code:
    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    class Layout{
    	public:
        Layout();
        ~Layout();
    	public:
    		virtual void func();
    };
    layout.cpp
    Code:
    #include "layout.h"
    Layout::Layout(){
    
    }
    Layout::~Layout(){
    
    }
    void Layout::func(){
    	cout<<"Layout::func()"<<endl;
    }
    mylayout.h
    Code:
    #include "layout.h"
    
    class MyLayout : public Layout{
    	public:
        MyLayout();
        ~MyLayout();
    	public:
        virtual void func();
    };
    mylayout.cpp
    Code:
    #include "mylayout.h"
    MyLayout::MyLayout(): Layout(){
    
    }
    MyLayout::~MyLayout(){
    
    }
    void MyLayout::func(){
    	cout<<"MyLayout::func()"<<endl;
    }
    app.h
    Code:
    #include "layout.h"
    
    class App{
    	public:
    		Layout layout;
    	public:
        App();
        App(Layout& lt);
        ~App();
        void exec();
    };
    app.cpp
    Code:
    App::App(){
    
    }
    App::App(Layout& lt):layout(lt){
    
    }
    App::~App(){
    
    }
    void App::exec(){
    	layout.func();
    }
    main.cpp
    Code:
    #include "app.h"
    #include "mylayout.h"
    
    using namespace std;
    
    int main(int argc, char *argv[]){
    	MyLayout l;
    	App a(l);
    	a.exec();
      return EXIT_SUCCESS;
    }

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The Layout member in your App class cannot be an object. It must be a pointer or reference (or smart pointer).

    In this specific example a reference would be fine.

  3. #3
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Daved View Post
    The Layout member in your App class cannot be an object. It must be a pointer or reference (or smart pointer).

    In this specific example a reference would be fine.
    Except, then the App() constructor needs to be removed [1] (it is not currently used anyways), as it is invalid


    [1] Or it could be rewritten to initialize the layout reference with a dummy layout that doesn't do anything.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  4. #4
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    So Polymorphic behaviour doesn't work without a reference or Pointer ????

    [1]Or it could be rewritten to initialize the layout reference with a dummy layout that doesn't do anything.
    Is it the only way to make a private member variable for dummy and use that or there is some other smart non-dirty way too ??

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by noobcpp View Post
    So Polymorphic behaviour doesn't work without a reference or Pointer ????
    Correct.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> So Polymorphic behaviour doesn't work without a reference or Pointer ???? <<

    Correct.


    >> Is it the only way to make a private member variable for dummy <<

    Does your app class make any sense without a Layout? If not, then don't provide a default constructor. If it does, then make it a pointer and mark it as null. Making Layout a reference can cause other problems, such as making the App not copyable. Its the right choice in some restrictive situations, but a more general solution is to use a pointer.

  7. #7
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Quote Originally Posted by Daved View Post
    >> Is it the only way to make a private member variable for dummy <<

    Does your app class make any sense without a Layout? If not, then don't provide a default constructor. If it does, then make it a pointer and mark it as null. Making Layout a reference can cause other problems, such as making the App not copyable. Its the right choice in some restrictive situations, but a more general solution is to use a pointer.
    Hmm Ok I'll try

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Daved View Post
    >> So Polymorphic behaviour doesn't work without a reference or Pointer ???? <<

    Correct.
    And the reason for this is that the compiler believes that if it's not a pointer, then there's no need to go through the hassle of looking up the function in a vtable, because you haven't given it any chance of being anything different from that class.

    Note that when you do "layout(lt)" you are actually copying only the "layout" part of the mylayout class, which means that if you had actually added some extra data in there, it would have got lost. So you are allowed to do that, but you risk loosing data. When it is a reference or pointer, then the new class can be any size it likes, because we do not copy the ACTUAL content, only the pointer to the class.

    --
    Mats
    Last edited by matsp; 10-01-2008 at 05:09 PM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Thanks I am using Pointers and It worked.
    Now another problem accured.
    I've a Class Called MyApp extends App.
    Code:
    class MyApp : public App{
    	public:
        MyApp();
        ~MyApp();
    };
    
    MyApp::MyApp() : App(){
    
    }
    MyApp::~MyApp(){
    
    }
    now When I try to use.
    Code:
    MyLayout* l = new MyLayout();
    MyApp a(l);
    Compiler Says:
    Code:
    error: no matching function for call to MyApp::MyApp(MyLayout*&)
    note: candidates are: MyApp::MyApp()
    note: MyApp::MyApp(const MyApp&)
    Why it says MyApp::MyApp(MyLayout*&) rather than MyApp::MyApp(MyLayout*) I am using g++ on debian.
    Last edited by noobcpp; 10-01-2008 at 11:46 PM.

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    You need to make the constructor of MyApp take a layout pointer and pass it to the base class in the initializer list.

    Although, you might want to do a little research on design patterns. This is very much the perfect example of one in particular (that I don't know the name of without looking up). If you find the right one you can find good C++ examples on how to model it.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Hard to say, it could be implemented as a method taking a pointer or a reference to a pointer, either would be fine. Your compiler probably assumes you're more likely to want to pass by reference, however there's no need to in this case.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Why it says MyApp::MyApp(MyLayout*&) rather than MyApp::MyApp(MyLayout*)
    The type G++ prints here is not of any function that exists (it is, after all, complaining that one doesn't), but of whatever type it has deduced from the arguments. Since you're passing an lvalue to the constructor, GCC represents that as a reference.
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  13. #13
    Registered User
    Join Date
    Jun 2007
    Posts
    219
    Class MyApp inherits App
    and App Class have a constructor
    Code:
    App(Layout* lt);
    and
    Class MyLayout inherits MyLayout

    so shouldn't the inherited Constructor exihibit Polymotphic behaviour ??
    another Question arises prior to above one which is are Parent Classe's constructors really inherited in the child Class ??
    If inherited can they be used from an Instance of Child Class ??

    Here one more thing That surprised me is
    Compiler's Error message:
    Code:
    error: no matching function for call to MyApp::MyApp(MyLayout*&)
    note: candidates are: MyApp::MyApp()
    note: MyApp::MyApp(const MyApp&)
    Here the candidates are MyApp()'s default constructor and the copy constructor written by compiler itself.
    But why the inherited constructors are not listed over there ??

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Inherited constructors do not automatically become the derived class's constructors.
    Just because App has a constructor that takes MyLayout* as argument doesn't mean there's one for MyApp.
    You need to create a MyApp constructor that takes a MyLayout* as argument and can then pass it on to the base class's constructor for further constructing.

    And yes, all the constructors are inherited in the derived class.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    >> so shouldn't the inherited Constructor exihibit Polymotphic behaviour ??

    Constructors aren't polymorphic because you know the type of the object when you call the constructor. Polymorphism isn't about re-using base class code, it's about re-using code that uses a pointer or reference to the base class (when the compiler and the code don't know which derived class the pointer refers to).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Texture Management in OpenGL
    By Brafil in forum Game Programming
    Replies: 13
    Last Post: 07-16-2009, 04:32 PM
  2. Include Problems
    By loopshot in forum Game Programming
    Replies: 13
    Last Post: 02-17-2006, 03:22 PM
  3. Replies: 3
    Last Post: 10-31-2005, 12:05 PM
  4. Question on l-values.
    By Hulag in forum C++ Programming
    Replies: 6
    Last Post: 10-13-2005, 04:33 PM
  5. Replies: 3
    Last Post: 12-03-2001, 01:45 PM