inheritance problem

Discussion in 'C++' started by Gary Wessle, Nov 10, 2006.

  1. Gary Wessle

    Gary Wessle Guest

    Hi

    in the attempt below, I intend to use 2 derived classes whose objects
    c'tor fires a base class method which build a string "main_menu" which
    is a concatenation of the strings for each derived object c'tor
    argument. ok, let me explain in a different language; but before, here
    is the expected output

    preform Thread task.
    preform non-thread task.

    why did not it happen?
    thanks

    // the code.

    // task.h
    #ifndef TASK_H
    #define TASK_H
    #include <string>
    #include <vector>

    class Task {
    std::string main_menu;
    public:
    Task();
    void mm_build(std::string);
    void p_main_menu();
    };

    class Thr_task : public Task {
    public:
    Thr_task(std::string);
    };


    class No_thr_task : public Task {
    public:
    No_thr_task(std::string);
    };

    #endif


    ****************************************************************
    //task.cpp
    #include <sstream>
    using std::stringstream;
    #include <fstream>
    using std::ifstream;
    #include <iostream>
    using namespace std;

    #include "task.h"

    /* the base class */
    Task::Task(){
    p_main_menu();
    }

    void Task::p_main_menu(){
    cout << main_menu << endl;
    }

    void Task::mm_build(string s){
    main_menu + ".\n" + s;
    }


    /* the drived class 1 */
    Thr_task::Thr_task(string n)
    {
    Task::mm_build(n);
    }

    /* the drived class 2 */
    No_thr_task::No_thr_task(string n)
    {
    Task::mm_build(n);
    }


    ****************************************************************
    //main.cpp
    #include <iostream>
    using std::cout;
    using std::endl;
    #include "task.h"

    int main() {
    Thr_task t1("preform Thread task");
    No_thr_task n1("preform non-thread task");
    Task dummy;
    }
    Gary Wessle, Nov 10, 2006
    #1
    1. Advertising

  2. Gary Wessle

    mlimber Guest

    Gary Wessle wrote:
    > Hi
    >
    > in the attempt below, I intend to use 2 derived classes whose objects
    > c'tor fires a base class method which build a string "main_menu" which
    > is a concatenation of the strings for each derived object c'tor
    > argument. ok, let me explain in a different language; but before, here
    > is the expected output
    >
    > preform Thread task.
    > preform non-thread task.
    >
    > why did not it happen?
    > thanks
    >
    > // the code.
    >
    > // task.h
    > #ifndef TASK_H
    > #define TASK_H
    > #include <string>
    > #include <vector>


    You don't use vector.

    >
    > class Task {
    > std::string main_menu;
    > public:
    > Task();
    > void mm_build(std::string);


    You should be passing all strings here by const reference. See:

    http://www.parashift.com/c -faq-lite/const-correctness.html#faq-18.1

    > void p_main_menu();
    > };
    >
    > class Thr_task : public Task {
    > public:
    > Thr_task(std::string);
    > };
    >
    >
    > class No_thr_task : public Task {
    > public:
    > No_thr_task(std::string);
    > };
    >
    > #endif
    >
    >
    > ****************************************************************
    > //task.cpp
    > #include <sstream>
    > using std::stringstream;
    > #include <fstream>
    > using std::ifstream;
    > #include <iostream>
    > using namespace std;


    Why explicitly specify stringstream and ifstream when you also use the
    whole std namespace, which brings both into scope anyway? Also, you
    don't use either of those classes. Please post minimal code
    (http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8) so as
    not to confuse things.

    >
    > #include "task.h"


    Stylistically, I prefer to put all using statements after *all* headers
    so that the headers don't have extra (and perhaps unexpected) symbols
    in the global namespace.

    >
    > /* the base class */
    > Task::Task(){
    > p_main_menu();
    > }
    >
    > void Task::p_main_menu(){
    > cout << main_menu << endl;
    > }
    >
    > void Task::mm_build(string s){
    > main_menu + ".\n" + s;
    > }
    >
    >
    > /* the drived class 1 */
    > Thr_task::Thr_task(string n)
    > {
    > Task::mm_build(n);
    > }


    There's no need to qualify mm_build here. There's no other mm_build in
    this scope. Anywho, here's what this constructor implicitly does:

    Thr_task::Thr_task(string n)
    : Task()
    {
    Task::mm_build(n);
    }

    The base class constructor has already been called before you build the
    menu. Why not have the Task constructor accept a string, which it then
    uses to build a menu and, if you must, print it? Better yet, have the
    derived constructors or the user call the print function.

    > /* the drived class 2 */
    > No_thr_task::No_thr_task(string n)
    > {
    > Task::mm_build(n);
    > }
    >
    >
    > ****************************************************************
    > //main.cpp
    > #include <iostream>
    > using std::cout;
    > using std::endl;
    > #include "task.h"
    >
    > int main() {
    > Thr_task t1("preform Thread task");
    > No_thr_task n1("preform non-thread task");
    > Task dummy;
    > }


    Cheers! --M
    mlimber, Nov 10, 2006
    #2
    1. Advertising

  3. Gary Wessle

    Gary Wessle Guest

    another variation gave me more errors

    ****************************************************************
    #ifndef TASK_H
    #define TASK_H
    #include <string>
    #include <vector>

    class Task {
    static std::string main_menu;
    public:
    Task(std::string);
    void p_main_menu();
    };

    class Thr_task : public Task {
    public:
    Thr_task(std::string);
    };


    class No_thr_task : public Task {
    public:
    No_thr_task(std::string);
    };

    #endif

    ****************************************************************

    #include <sstream>
    using std::stringstream;
    #include <fstream>
    using std::ifstream;
    #include <iostream>
    using std::cout;
    using std::endl;
    #include <string>
    using std::string;

    using namespace std;

    #include "task.h"

    /* the base class */
    Task::Task(string s)
    {
    main_menu = main_menu + ".\n" + s; //<<<<<<< line 18
    }

    void Task::p_main_menu(){
    cout << main_menu << endl; //<<<<<<<<< line 22
    }

    /* the drived class 1 */
    Thr_task::Thr_task(string n):
    Task(n)
    {
    }

    /* the drived class 2 */
    No_thr_task::No_thr_task(string n):
    Task(n)
    {
    }

    ****************************************************************

    #include <iostream>
    using std::cout;
    using std::endl;
    #include "task.h"

    int main() {
    Thr_task t1("preform Thread task");
    No_thr_task n1("preform non-thread task");
    Task dummy("");
    }

    ****************************************************************

    cd /home/fred/myProg/try/
    make -k
    g++ -gdwarf-2 -c -o task.o task.cpp
    g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
    task.o: In function `Task::p_main_menu()':
    /home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
    task.o: In function `Task':
    /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    collect2: ld returned 1 exit status
    make: *** [proj] Error 1

    Compilation exited abnormally with code 2 at Fri Nov 10 14:11:35
    Gary Wessle, Nov 10, 2006
    #3
  4. Gary Wessle

    Salt_Peter Guest

    Gary Wessle wrote:
    > another variation gave me more errors
    >
    > ****************************************************************
    > #ifndef TASK_H
    > #define TASK_H
    > #include <string>
    > #include <vector>
    >
    > class Task {
    > static std::string main_menu;


    don't use static members until you understand the implications and how
    to initialize them.

    > public:
    > Task(std::string);


    Always pass by reference, by const reference.
    Otherwise copies can get very expensive.

    > void p_main_menu();


    Does that function modify the object: no
    Make it const.

    > };
    >
    > class Thr_task : public Task {
    > public:
    > Thr_task(std::string);


    by const ref

    > };
    >
    >
    > class No_thr_task : public Task {
    > public:
    > No_thr_task(std::string);


    by const ref

    > };
    >
    > #endif
    >
    > ****************************************************************
    >
    > #include <sstream>
    > using std::stringstream;
    > #include <fstream>
    > using std::ifstream;
    > #include <iostream>
    > using std::cout;
    > using std::endl;
    > #include <string>
    > using std::string;
    >
    > using namespace std;
    >
    > #include "task.h"
    >
    > /* the base class */
    > Task::Task(string s)
    > {
    > main_menu = main_menu + ".\n" + s; //<<<<<<< line 18
    > }


    use the init list, see code below

    >
    > void Task::p_main_menu(){
    > cout << main_menu << endl; //<<<<<<<<< line 22
    > }
    >
    > /* the drived class 1 */
    > Thr_task::Thr_task(string n):
    > Task(n)
    > {
    > }
    >
    > /* the drived class 2 */
    > No_thr_task::No_thr_task(string n):
    > Task(n)
    > {
    > }
    >
    > ****************************************************************
    >
    > #include <iostream>
    > using std::cout;
    > using std::endl;
    > #include "task.h"
    >
    > int main() {
    > Thr_task t1("preform Thread task");
    > No_thr_task n1("preform non-thread task");
    > Task dummy("");
    > }
    >
    > ****************************************************************
    >
    > cd /home/fred/myProg/try/
    > make -k
    > g++ -gdwarf-2 -c -o task.o task.cpp
    > g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
    > task.o: In function `Task::p_main_menu()':
    > /home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
    > task.o: In function `Task':
    > /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    > /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    > /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    > /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    > collect2: ld returned 1 exit status
    > make: *** [proj] Error 1
    >
    > Compilation exited abnormally with code 2 at Fri Nov 10 14:11:35


    #include <iostream>
    #include <string>

    class Task {
    std::string main_menu;
    public:
    Task(const std::string&);
    void p_main_menu() const;
    };

    Task::Task(const std::string& s)
    : main_menu(".\n" + s)
    {
    }

    void Task::p_main_menu() const
    {
    std::cout << main_menu << std::endl;
    }

    class Thr_task : public Task {
    public:
    Thr_task(const std::string&);
    };

    Thr_task::Thr_task(const std::string& s)
    : Task(s)
    {
    }

    class No_thr_task : public Task {
    public:
    No_thr_task(const std::string&);
    };

    No_thr_task::No_thr_task(const std::string& s)
    : Task(s)
    {
    }

    int main()
    {
    Thr_task tt("preform Thread task");
    tt.p_main_menu();

    No_thr_task ntt("preform non-thread task");
    ntt.p_main_menu();

    Task dummy("dummy");
    dummy.p_main_menu();
    }

    /*
    ..
    preform Thread task
    ..
    preform non-thread task
    ..
    dummy
    */
    Salt_Peter, Nov 10, 2006
    #4
  5. Gary Wessle

    Gary Wessle Guest

    "mlimber" <> writes:

    > Gary Wessle wrote:
    > > Hi
    > >
    > > in the attempt below, I intend to use 2 derived classes whose objects
    > > c'tor fires a base class method which build a string "main_menu" which
    > > is a concatenation of the strings for each derived object c'tor
    > > argument. ok, let me explain in a different language; but before, here
    > > is the expected output
    > >
    > > preform Thread task.
    > > preform non-thread task.
    > >
    > > why did not it happen?
    > > thanks
    > >
    > > ...
    > > #include <vector>

    >
    > You don't use vector.
    >
    > >
    > > ...
    > > void mm_build(std::string);

    >
    > You should be passing all strings here by const reference. See:
    >
    > http://www.parashift.com/c -faq-lite/const-correctness.html#faq-18.1
    >
    > > void p_main_menu();
    > > };
    > > ...
    > > #include <sstream>
    > > using std::stringstream;
    > > #include <fstream>
    > > using std::ifstream;
    > > #include <iostream>
    > > using namespace std;

    >
    > Why explicitly specify stringstream and ifstream when you also use the
    > whole std namespace, which brings both into scope anyway? Also, you
    > don't use either of those classes. Please post minimal code
    > (http://www.parashift.com/c -faq-lite/how-to-post.html#faq-5.8) so as
    > not to confuse things.
    >
    > >
    > > #include "task.h"

    >
    > Stylistically, I prefer to put all using statements after *all* headers
    > so that the headers don't have extra (and perhaps unexpected) symbols
    > in the global namespace.
    >
    > >
    > >...
    > >
    > > /* the drived class 1 */
    > > Thr_task::Thr_task(string n)
    > > {
    > > Task::mm_build(n);
    > > }

    >
    > There's no need to qualify mm_build here. There's no other mm_build in
    > this scope. Anywho, here's what this constructor implicitly does:
    >
    > Thr_task::Thr_task(string n)
    > : Task()
    > {
    > Task::mm_build(n);
    > }
    >
    > The base class constructor has already been called before you build the
    > menu. Why not have the Task constructor accept a string, which it then
    > uses to build a menu and, if you must, print it? Better yet, have the
    > derived constructors or the user call the print function.
    >
    > > /* the drived class 2 */
    > > ...

    >
    > Cheers! --M


    I tried many ways to get this to work, the best I can do is as follows
    but still getting the error

    ****************************************************************
    cd /home/fred/myProg/try/
    make -k
    g++ -gdwarf-2 -c -o task.o task.cpp
    g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
    task.o: In function `Task::print_mm()':
    /home/fred/myProg/try/task.cpp:19: undefined reference to `Task::main_menu'
    task.o: In function `Task':
    /home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:14: undefined reference to `Task::main_menu'
    collect2: ld returned 1 exit status
    make: *** [proj] Error 1

    Compilation exited abnormally with code 2 at Fri Nov 10 17:23:05


    //task.h
    ****************************************************************
    #ifndef TASK_H
    #define TASK_H
    #include <string>

    class Task {
    static std::string main_menu;
    public:
    Task(std::string);
    void print_mm();
    };

    class Thr_task : public Task {
    public:
    Thr_task(std::string);
    void print_menu();
    };


    class No_thr_task : public Task {
    public:
    No_thr_task(std::string);
    };

    #endif

    //task.cpp
    ****************************************************************
    1 #include <iostream>
    2 #include <string>
    3 using std::cout;
    4 using std::endl;
    5 using std::string;
    6
    7 using namespace std;
    8
    9 #include "task.h"
    10
    11 /* the base class */
    12 Task::Task(string s)
    13 {
    14 main_menu = main_menu + ".\n" + s;
    15 }
    16
    17 void Task::print_mm(){
    18
    19 cout << main_menu << endl;
    20 }
    21
    22 /* the drived class 1 */
    23 Thr_task::Thr_task(const string n) :
    24 Task(n)
    25 {
    26 }
    27 void Thr_task::print_menu(){
    28 print_mm();
    29 }
    30
    31 /* the drived class 2 */
    32 No_thr_task::No_thr_task(const string n) :
    33 Task(n)
    34 {
    35 }

    //main.cpp
    ****************************************************************
    #include "task.h"

    int main() {
    Thr_task t1("preform Thread task");
    No_thr_task n1("preform non-thread task");
    Thr_task dummy(""); //only to print the main_menu
    dummy.print_menu();
    }
    Gary Wessle, Nov 10, 2006
    #5
  6. Gary Wessle

    Gary Wessle Guest

    "Salt_Peter" <> writes:

    > Gary Wessle wrote:
    > > another variation gave me more errors

    ....

    the idea I had in mind is to create objects of derived classes and
    once I finish creating them, I then print the main_menu. not to print
    the menu ever time I create an object. and that is why I thought to
    use the static std::string main_menu.
    once the menu prints it should show "as its items" the string passed
    to the derived class c'tor.
    Gary Wessle, Nov 10, 2006
    #6
  7. Gary Wessle

    Gary Wessle Guest

    "Salt_Peter" <> writes:

    here is the code after all the fixes plus trying to use a static
    member to hold the menu items from previous derived class objects.
    since my idea is to initialize different derived class objects and
    then print a menu listing them in the order they were created. i.e
    1. preform Thread task.
    2. preform non-thread task.
    3. preform whatever.

    thus I need to create the objects from their correct type like this

    Thr_task t1("preform Thread task.");
    No_thr_task n1("preform non-thread task.");
    Whatever_type w1("preform whatever task.");

    and if possible with the least typing "with out printing each time I
    create an object" but only when I signal printing the whole menu.
    maybe like
    base_class bc("");
    bc.print_mm();
    cout << "please make a selection from the menu: " << endl;

    I read a bit and fount that I have to set a static member and a static
    member function to work with it, note below.

    //task.h
    ****************************************************************
    #ifndef TASK_H
    #define TASK_H
    #include <string>

    class Task {
    static std::string main_menu;
    public:
    Task(const std::string&);
    static void build_mm( const std::string& );
    void print_mm() const;
    };

    class Thr_task : public Task {
    public:
    Thr_task(const std::string&);
    void print_menu() const;
    };


    class No_thr_task : public Task {
    public:
    No_thr_task(const std::string&);
    };

    #endif





    //task.cpp
    ****************************************************************
    1 #include <iostream>
    2 #include <string>
    3 using std::cout;
    4 using std::endl;
    5 using std::string;
    6
    7 using namespace std;
    8
    9 #include "task.h"
    10
    11 /* the base class */
    12 Task::Task(const string& s)
    13 {
    14 build_mm(s);
    15 }
    16
    17 void Task::print_mm() const {
    18 cout << main_menu << endl;
    19 }
    20
    21 void Task::build_mm(const string& s){
    22 main_menu = main_menu + ".\n" + s;
    23 }
    24
    25 /* the drived class 1 */
    26 Thr_task::Thr_task(const string& n) :
    27 Task(n)
    28 {
    29 }
    30 void Thr_task::print_menu() const {
    31 print_mm();
    32 }
    33
    34 /* the drived class 2 */
    35 No_thr_task::No_thr_task(const string& n) :
    36 Task(n)
    37 {
    38 }




    //main.cpp
    ****************************************************************
    #include "task.h"

    int main() {
    Thr_task t1("preform Thread task");
    No_thr_task n1("preform non-thread task");
    Thr_task dummy("");
    dummy.print_mm();
    }




    //error
    ****************************************************************

    cd ~/myProg/try/
    make -k
    g++ -gdwarf-2 -c -o main.o main.cpp
    g++ -Wall -gdwarf-2 -o proj handle.o main.o swi_board.o task.o
    task.o: In function `Task::build_mm(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
    /home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
    /home/fred/myProg/try/task.cpp:22: undefined reference to `Task::main_menu'
    task.o: In function `Task::print_mm() const':
    /home/fred/myProg/try/task.cpp:18: undefined reference to `Task::main_menu'
    collect2: ld returned 1 exit status
    make: *** [proj] Error 1

    Compilation exited abnormally with code 2 at Fri Nov 10 20:35:08
    Gary Wessle, Nov 10, 2006
    #7
  8. Gary Wessle

    Gary Wessle Guest

    another way I can do this is to make each task remember its menu item and
    create a vector<Task*> in main.cpp, puch each item on it and loop and call
    print_menu_item or even preform upon selection, i.e
    vector<Task*> vTp.
    *(vTp.print_menu_item)
    that can do it, what you think?
    Gary Wessle, Nov 10, 2006
    #8
  9. Gary Wessle wrote:

    > another way I can do this is to make each task remember its menu item and
    > create a vector<Task*> in main.cpp, puch each item on it and loop and call
    > print_menu_item or even preform upon selection, i.e
    > vector<Task*> vTp.
    > *(vTp.print_menu_item)
    > that can do it, what you think?


    It seems maybe you have your classes trying to do too much. Try to farm
    off the menu generation to another set of classes to the task
    execution. This will also make it easier to manage translation of the
    menus should you need to do that. In any case the task class will be
    simpler as it won't have to worry about display and the seperate
    display classes will be simpler as they won't have to worry about
    executing the classes.


    K
    =?iso-8859-1?q?Kirit_S=E6lensminde?=, Nov 10, 2006
    #9
  10. Gary Wessle

    Salt_Peter Guest

    Gary Wessle wrote:
    > "Salt_Peter" <> writes:
    >
    > > Gary Wessle wrote:
    > > > another variation gave me more errors

    > ...
    >
    > the idea I had in mind is to create objects of derived classes and
    > once I finish creating them, I then print the main_menu. not to print
    > the menu ever time I create an object. and that is why I thought to
    > use the static std::string main_menu.
    > once the menu prints it should show "as its items" the string passed
    > to the derived class c'tor.


    How you plan to use your classes and objects are not my concern. I just
    output the string to check whether these worked or not. What i might
    suggest is simply use one of those classes and generate a vector of
    menu items. I can see something like < > to inactivate them and <-> to
    disactivate the item. You might implement a callback mechanism to
    "talk" to the menu.
    Salt_Peter, Nov 10, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. maxw_cc
    Replies:
    1
    Views:
    3,112
    Martijn van Steenbergen
    Dec 21, 2003
  2. cppsks
    Replies:
    0
    Views:
    798
    cppsks
    Oct 27, 2004
  3. karthikbalaguru
    Replies:
    9
    Views:
    1,022
  4. Daniel Pitts
    Replies:
    27
    Views:
    1,864
    Mike Schilling
    Feb 27, 2008
  5. johnsonlau
    Replies:
    1
    Views:
    757
    Kai-Uwe Bux
    Jul 21, 2008
Loading...

Share This Page