0

I'm trying to code a class to handle joystick input (irrelevant), and being rusty on inheritance and new to c++ I'm having some confusion while trying to create a subclass of my joystick class. Here's my code

//superclass's .h
#ifndef JOYSTICKINPUT_H
#define JOYSTICKINPUT_H

#include "WPILib.h"

class JoystickInput {
    public:
        JoystickInput(Joystick*);
        Joystick * joystick;
        Victor * myVictor [3];
        bool buttons [10];
        bool buttonClicked(int id);
        void testForActions();
};
#endif

And here's its definition

//superclass's .cpp
#include "JoystickInput.h"

JoystickInput::JoystickInput(Joystick * joy) {
    joystick = joy;
    for (int x = 0; x < 10; x++) {
        buttons[x] = false;
    }
}

bool JoystickInput::buttonClicked(int id) {
    if (buttons[id] == false and joystick->GetRawButton(id) == true) {
        buttons[id] = true;
        return true;
    } else if (buttons[id] == true and joystick->GetRawButton(id) == false) {
        buttons[id] = false;
        return false;
    } else {
        return false;
    }
}

void JoystickInput::testForActions() {
}

Now I'm trying to extend this with a JoystickOne class, as its behavior is slightly different. To this end I created a JoystickOne.h and a JoystickOne.cpp

//Joystickone.h
#ifndef JOYSTICKONE_H
#define JOYSTICKONE_H
#include "WPILib.h"
#include "JoystickInput.h"

class JoystickOne : public JoystickInput {
    public:
        JoystickOne(Joystick*);
        Joystick * joystick;
        Victor * myVictor;
        bool buttons [10];
        bool buttonClicked(int id);
        void testForActions();
};
#endif

And the .cpp

    #include "JoystickOne.h"
#include "WPILib.h"

JoystickOne::JoystickOne(Joystick * joy) : JoystickInput(joy) {
    //joystick = joy;
    //myVictor = new Victor(1);
    /*for (int x = 0; x < 10; x++) {
        buttons[x] = false;
    }*/
}

bool JoystickOne::buttonClicked(int id) {
    if (buttons[id] == false and joystick->GetRawButton(id) == true) {
        buttons[id] = true;
        return true;
    } else if (buttons[id] == true and joystick->GetRawButton(id) == false) {
        buttons[id] = false;
        return false;
    } else {
        return false;
    }
}

void JoystickOne::testForActions() {
    if (buttonClicked(1)) {
    }
    if (buttonClicked(2)) {
    }
    if (buttonClicked(3)) {
        //myVictor->Set(.3);
    }
    if (buttonClicked(4)) {
    }
}

My problem is that I'm not quite sure what's extraneous in the JoystickOne class. I come from Java, so I'm used to being able to just extend a superclass and automatically use all of its methods and members. I'm confused because of C++'s seperation into .h and .cpp files; from what I've learned by messing around I have to declare all variables and methods I wish to use, even if they're members of the superclass. I don't think I have to define method buttonClicked() twice, although I don't have a robot so I can't actually test that now.

Basically, I'm asking what I can cut out from the definition of the JoystickOne class, and how to do it. If any of you have advice on some good OOP practices in C++ feel free to share, or maybe even clear up some java-isms that I have.

Thanks!

pipsqueaker117
  • 2,280
  • 9
  • 35
  • 47
  • 1
    You don't have to redeclare superclass members in child class. Just declare all members you wish to share between superclass and its children using `protected`keyword. Methods you want to be overwritten should be marked as `virtual` in superclass. And that's it. Apart from that inheritance is quite the same in c++ and java. – Greg0ry May 01 '13 at 20:51
  • 1
    I guess you could find it useful to go through some simple tutorial about inheritance in c++ :-) How about this one: http://www.cplusplus.com/doc/tutorial/classes/ – Greg0ry May 01 '13 at 20:53
  • `from what I've learned by messing around I have to declare all variables and methods I wish to use, even if they're members of the superclass` Nope. – Lightness Races in Orbit May 01 '13 at 20:53
  • 2
    @Greg0ry: Let's _not_ recommend those terrible tutorials. How about a good book: http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list – Lightness Races in Orbit May 01 '13 at 20:53
  • @`Lightness Races in Orbit` - ahh, tutorials are not that bad if you just want to doublecheck principles instead of posting silly questions on stackoverflow ;-) just kiddin', there are no bad questions, only bad answers :-) – Greg0ry May 01 '13 at 20:56

3 Answers3

4

You should mark methods that can be overridden as virtual in your base class. To override it in a derived class, simply re-define it in your derived class.

Example:

class Base{
public:
  virtual void overrideThis() { std::cout << "Base" << std::end; }
  void test() { std::cout << "Base::test()" << std::endl; }
};

class Derived : public Base{
public:
  void overrideThis() { std::cout << "Derived" << std::endl; }
};

Now if you instantiate:

Derived d;
d.overrideThis(); // Will print 'Derived'
d.test(); // Will print 'Base::test()'

As for member variables. Private members defined in your base will class will NOT be available in your derived class. On the other hand, protected and public member variables will be accessible.

codah
  • 466
  • 4
  • 14
Ryan
  • 1,797
  • 12
  • 19
  • I think your answer is misleading. Members which are not marked as `virtual` are also inherited. `virtual` only marks those members that can (but dont need to) be re-defined in the derived classes. – psibar May 01 '13 at 21:04
3

You need to use the virtual keyword to make your functions inheritable. Furthermore, you can declare functions such as

buttonClicked(int id) = 0;

This will be the equivalent of an abstract methods.

You should not need to redefine variables, they should be automatically inherited if public or protected. Also note that you should declare your destructors virtual at all times, otherwise inherited classes will not be able to delete their own stuff.

Eric
  • 19,525
  • 19
  • 84
  • 147
0

No you don't have to re-declare the attributes in your inherited/child class, so remove those. Generally make them private (usable by parent class only) or protected (usable by parent and child classes) not public. With your methods, only 're-declare' them (override) if they act differently in the child class, and make sure you declare them virtual in the parent class. Experimenting is good.. remove some stuff, add lots of print statements, and see how it behaves :) It's not SO different from Java* apart from the .h/.cpp thing.

*At the basic level

codah
  • 466
  • 4
  • 14