Page 1 of 2 12 LastLast
Results 1 to 20 of 24

Thread: Defining shared class member functions only once

  1. #1
    Join Date
    Jan 2011
    Posts
    70
    Thanks
    43
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Defining shared class member functions only once

    I couldn't really figure out how to form the question in a way that makes sense in a search engine, so if this has been asked already by someone else I apologize.

    I have a set of classes, some of which have a member function, setRGB(quint16, int) for example, that does the exact same thing. I'd like to clean up my code so that setRGB is only defined once without resorting to external functions because it accesses private variables.

    They all inherit from an abstract core class. For clarity's sake I don't want them to inherit from each other, so inheritance isn't really an option. I'm open to the idea of templates, but as I have never designed one before, I'm not sure when it's appropriate to use that concept.

    Here's an example. A, B, and C all inherit from CORE:
    Qt Code:
    1. //stuff.h
    2. //use a shortcut macro to reduce error from copy-pasting
    3. #define PTRGB \
    4. public: \
    5. quint16 setRGB(quint16 v, int i); \
    6. quint16 getRGB(int i) const {return rgb[i]}; \
    7. private: \
    8. quint16 rgb[3];
    9.  
    10. class CORE
    11. {
    12. public:
    13. virtual quint16 setRGB(quint16 v, int i);
    14. virtual quint16 getRGB(int i) const {return 0;}
    15. //other functions and variables common to all of my classes
    16. };
    17.  
    18. class A : public CORE
    19. {
    20. PTRGB
    21. private:
    22. int extraVariable;
    23. }
    24.  
    25. class B : public CORE
    26. {
    27. //doesn't have setRGB implemented!
    28. private:
    29. double aDifferentExtraVariable;
    30. public:
    31. double getSpecialB() {return aDifferentExtraVariable;}
    32. }
    33.  
    34. class C : public CORE
    35. {
    36. PTRGB
    37. private:
    38. bool isBlue;
    39. public:
    40. bool getIsBlue() {return isBlue;}
    41. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. //stuff.cpp
    2. quint16 CORE::setRGB(quint16 v, int i)
    3. {
    4. return 0;
    5. }
    6.  
    7. quint16 A::setRGB(quint16 v, int i)
    8. {
    9. #ifdef DEBUGMODE
    10. if(i < 0 || i > 2)
    11. {
    12. qWarning() << "Index to setRGB is out of range.";
    13. return 0;
    14. }
    15. #endif
    16. return rgb[i] = v;
    17. }
    18.  
    19. quint16 C::setRGB(quint16 v, int i)
    20. {
    21. #ifdef DEBUGMODE
    22. if(i < 0 || i > 2)
    23. {
    24. qWarning() << "Index to setRGB is out of range.";
    25. return 0;
    26. }
    27. #endif
    28. return rgb[i] = v;
    29. }
    To copy to clipboard, switch view to plain text mode 
    As far as I can tell, I can't do a similar macro for the definitions like I did with the declarations because of the class name in the "quint16 C::setRGB(quint16 v, int i)" lines, but I'm looking for similar functionality.

    Any ideas?

  2. #2
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Defining shared class member functions only once

    I was just looking for the exact thing you're trying to achieve, but I haven't got any good answer.. Actually I share those private members through a special class constructor and I define my functions in that class. I don't want to share those members, but it seems it is impossible without doing it. Probably the best I can do is passing a reference to the member each time I need to use it rather than storing that reference in a pointer.

    Greetings!

  3. #3
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,391
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Defining shared class member functions only once

    A, B, and C all inherit from CORE:
    You can introduce another class that extends CORE, lets say CORE_RGB, so it'll look like this:
    Qt Code:
    1. //stuff.h
    2.  
    3. //use a shortcut macro to reduce error from copy-pasting
    4.  
    5. #define PTRGB \
    6.  
    7. public: \
    8.  
    9. quint16 setRGB(quint16 v, int i); \
    10.  
    11. quint16 getRGB(int i) const {return rgb[i]}; \
    12.  
    13. private: \
    14.  
    15. quint16 rgb[3];
    16.  
    17.  
    18.  
    19. class CORE
    20.  
    21. {
    22.  
    23. public:
    24.  
    25. virtual quint16 setRGB(quint16 v, int i);
    26.  
    27. virtual quint16 getRGB(int i) const {return 0;}
    28.  
    29. //other functions and variables common to all of my classes
    30.  
    31. };
    32.  
    33. class CORE_RGB : public CORE{
    34. PTRGB
    35. // there is no need for the macro now btw
    36. };
    37.  
    38. class A : public CORE_RGB
    39.  
    40. {
    41. private:
    42.  
    43. int extraVariable;
    44.  
    45. }
    46.  
    47.  
    48.  
    49. class B : public CORE
    50.  
    51. {
    52. //doesn't have setRGB implemented, because it extends CORE, not CORE_RGB
    53. private:
    54.  
    55. double aDifferentExtraVariable;
    56.  
    57. public:
    58.  
    59. double getSpecialB() {return aDifferentExtraVariable;}
    60.  
    61. }
    62.  
    63.  
    64.  
    65. class C : public CORE_RGB
    66.  
    67. {
    68. private:
    69.  
    70. bool isBlue;
    71.  
    72. public:
    73.  
    74. bool getIsBlue() {return isBlue;}
    75.  
    76. }
    To copy to clipboard, switch view to plain text mode 
    In the end, all A,B,C classes extends CORE as you wanted, and RGB methods are defined only in one place.

  4. The following user says thank you to stampede for this useful post:

    Phlucious (14th December 2011)

  5. #4
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Defining shared class member functions only once

    It is probably the best idea that can work for you, Phlucious. I was thinking it could work for me, but, what if the needed variables are part of UI? I would have to create private variable pointers because I have no access to the ui pointer from the base.

    PD: Should I create a new thread?

    Greetings

  6. #5
    Join Date
    Jan 2011
    Posts
    70
    Thanks
    43
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Thanks for the suggestion, Stampede. Something along those lines will probably work, but here's an added complication. Each class has a different combination of about 5 options, one of those being RGB as in the above example. For example, class A has RGB & TIME, class B has only TIME, class C has RGB & ALPHA, class D has ALPHA & TIME, etc.

    Basically what I'm talking about is akin to Qt's property system, except there's about 10 classes that mix & match which properties they actually have... each property with a custom get/set function. So the problem with extending CORE is that not all classes with TIME also have RGB (for example).

    Any suggestions or further comments?

  7. #6
    Join Date
    Apr 2011
    Posts
    9
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Defining shared class member functions only once

    You could create a class for RGB, a class for TIME, a class for ALPHA, and then inherit from every one you need.

    Greetings

  8. #7
    Join Date
    Jan 2011
    Posts
    70
    Thanks
    43
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by dancas2 View Post
    You could create a class for RGB, a class for TIME, a class for ALPHA, and then inherit from every one you need.
    While this idea is sound in theory, it doesn't quite work in my current execution. I store in a std::vector about 2-20 million abstract CORE* pointers that point to an instantiation of A, B, C, etc. I can do this since all of the functions in ABCD exist as a prototype in CORE.

    Therefore, I'm not sure what would happen if, for example, CORE_RGB & CORE_TIME inherited from CORE, and A inherited from both CORE_RGB & CORE_TIME.

  9. #8
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    why cant

    quint16 rgb[3]

    be protected and in CORE?

    Therefore, I'm not sure what would happen if, for example, CORE_RGB & CORE_TIME inherited from CORE, and A inherited from both CORE_RGB & CORE_TIME.
    Currently, nothing bad, since CORE is only an interface. If you put members variables into CORE, then you need to inherit CORE virtually, to avoid the dreaded diamond

    I can do this since all of the functions in ABCD exist as a prototype in CORE.
    This begs the question, why do all types implement all members? It looks the the change in behaviour hasnt be encapsulated properly.
    Last edited by amleto; 18th December 2011 at 15:45.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  10. #9
    Join Date
    Jan 2011
    Posts
    70
    Thanks
    43
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Thanks for your response!

    Quote Originally Posted by amleto View Post
    why cant
    quint16 rgb[3]
    be protected and in CORE?
    Normally I would just make a class that encapsulates every possible combination and be done with it, drastically simplifying my code. The problem rests in the problem of scale—when you have an extra 60 bytes (more or less) per record floating around, and around 6,000,000 records, that's an extra 343MB that I need to drag around. I'm already pushing the available memory as it is, so my intent is to only include RGB/TIME/ALPHA when the records actually have that data.

    Quote Originally Posted by amleto View Post
    If you put members variables into CORE, then you need to inherit CORE virtually, to avoid the dreaded diamond.
    Can you please elaborate on this? I'm not a programmer by training, so I'm unfamiliar with some of the lingo. Also, what do you mean by inheriting it virtually? I've never been clear on the functional distinction between Protected and Private. If I make the prototyped member functions of CORE protected, then my generalized manipulation functions (using CORE* pointers, though the object pointed to will be A, B, C, or D depending on the data imported) throw a compiler error.

  11. #10
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Hi,

    You could create a 'class' or 'type' RGB which has public members r, g and b. It would have a method setRGB() to set these three members, and also the other member functions you mention.

    The A and C classes would have a member of type RGB, say m_rgb. If a method in this class would need to know anything about the color, it would use the members m_rgb.r, m_rgb.g and m_rgb.b.

    This way you don't have to implement anything in your base classes, or in any other class in which you would like to use a color.

    Best regards,
    Marc

  12. #11
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by Phlucious View Post
    Thanks for your response!


    Normally I would just make a class that encapsulates every possible combination and be done with it, drastically simplifying my code. The problem rests in the problem of scale—when you have an extra 60 bytes (more or less) per record floating around, and around 6,000,000 records, that's an extra 343MB that I need to drag around. I'm already pushing the available memory as it is, so my intent is to only include RGB/TIME/ALPHA when the records actually have that data.


    Can you please elaborate on this? I'm not a programmer by training, so I'm unfamiliar with some of the lingo. Also, what do you mean by inheriting it virtually? I've never been clear on the functional distinction between Protected and Private. If I make the prototyped member functions of CORE protected, then my generalized manipulation functions (using CORE* pointers, though the object pointed to will be A, B, C, or D depending on the data imported) throw a compiler error.
    inheriting virtualy is not to do with access level (public/private/protected).

    If you have some base class B, and class A and class C both inherit B, then some other class, D is designed that wants to inherit A and C we have a problem IF B has data members.

    Qt Code:
    1. B
    2. /\
    3. A C
    4. \/
    5. D
    To copy to clipboard, switch view to plain text mode 

    If B has data members, then they exist as part of A, and ALSO as part of C. This is a big problem. To get around this, inherit B virtually (use virtual keyword like virtual method). Then if some class has multiple instances of B, only one will actually be made.


    However, since you say you can't use the members in the base class, you wont have this problem.
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  13. The following user says thank you to amleto for this useful post:

    Phlucious (27th December 2011)

  14. #12
    Join Date
    Jan 2011
    Posts
    70
    Thanks
    43
    Thanked 4 Times in 2 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Thank you for the great suggestion! Inheriting virtually seems to have the intended results. Following your diamond structure...

    Qt Code:
    1. class B {}
    2. class A : virtual public B {}
    3. class C : virtual public B {}
    4. class D : public A, public C {}
    To copy to clipboard, switch view to plain text mode 

    Unfortunately, I get the C4250 "[derived class] inherits [overwritten method in derived class] via dominance" warning now for every virtual function I re-defined. I understand that this warning is for programmers that might be caught by surprise, but is there any syntactic way for me to indicate to MSVC2010 that I'm doing this on purpose?

    [edit]
    I found this link useful for understanding what you wrote:
    http://publib.boulder.ibm.com/infoce...%2Fcplr135.htm
    [/edit]

  15. #13
    Join Date
    Sep 2011
    Posts
    1,245
    Thanks
    3
    Thanked 127 Times in 126 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    this warning is a bit different - as long as you have read and undersand what it warns against, and that if you have two reimplemented virtuals at the same inheritance level, then that would be an error.

    you can supress warnings with #pragma or project settings

    http://msdn.microsoft.com/en-us/libr...=vs.80%29.aspx
    If you have a problem, CUT and PASTE your code. Do not retype or simplify it. Give a COMPLETE and COMPILABLE example of your problem. Otherwise we are all guessing the problem from a fabrication where relevant details are often missing.

  16. The following user says thank you to amleto for this useful post:

    Phlucious (29th December 2011)

  17. #14
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Still, I think multiple inheritance is not the right solution for your initial problem.

    Say you have a class 'bike', and if you have a class 'livingroom'. Both have a light that you can switch on and off. That doesn't mean it is a good idea to have a class 'light' and derive 'bike' and 'livingroom' from it.

    Given your level of expertise in C++, it might be better to keep things simple. Plain old library functions are still widely used. It is not because C++ supports object oriented design, that everything has to be implemented in an object-oriented fashion. And static 'utility' functions are also widely used for a class where the function doesn't work on an object itself, but sort of belongs to the class anyway.

    Regards,
    Marc

  18. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by marcvanriet View Post
    Say you have a class 'bike', and if you have a class 'livingroom'. Both have a light that you can switch on and off. That doesn't mean it is a good idea to have a class 'light' and derive 'bike' and 'livingroom' from it.
    What if you call the class 'Lightable' and not 'light'?
    Qt Code:
    1. class Lightable {
    2. public:
    3. virtual void enableLight() { ... }
    4. virtual void disableLight() { ... }
    5. };
    6.  
    7. class Bike : public Vehice, public Lightable { ... };
    8. class LivingRoom : public Chamber, public Lightable { ... };
    To copy to clipboard, switch view to plain text mode 
    Sounds reasonable to me...


    An alternative is to have an external helper class that implements solely the "shared" functionality and call that object's methods passing the object it is to manipulate. Then you need implementations of that class to handle objects of specific types (ones that have the "RGB" functionality and those of the "TIME" functionality). Patterns like 'visitor' or 'strategy' come to my mind here but probably more solutions are possible and viable.
    In the end you have one "instance" of functionality per class instead of having one per item which escapes the memory hog trap.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  19. #16
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by wysota View Post
    What if you call the class 'Lightable' and not 'light'?
    Sounds reasonable to me...
    Sure, but all depends on the situation. What if you then come across a bike of which the front light can be set to three states : on - blinking - off. And when there are multiple independently controlled lights in the chamber ? Unfortunately the OP didn't post enough details of the use case to say if each object can really have only 1 color. Maybe later on there could be objects that have a 'front' and 'back' color.

    I would probably prefer an interface like
    bike1->frontlight->enableLight();
    room1->ceilinglight->disableLight();
    room1->curtainlights->enableLight();
    If the 'frontlight' and so have a reference to the class of which they are member, events can be triggered when a light status changes if this is necessary.

    But again... all depends on the use case.

    Regards,
    Marc

  20. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by marcvanriet View Post
    Sure, but all depends on the situation. What if you then come across a bike of which the front light can be set to three states : on - blinking - off. And when there are multiple independently controlled lights in the chamber ?
    Then you extend the Lightable interface. What you say applies to any class, inheritance, single or multiple, is irrelevant here. If you continue this way, you'll reach a conclusion that there is no point in creating classes at all because some day you might want to change something in your program breaking what you did before.



    I would probably prefer an interface like
    bike1->frontlight->enableLight();
    room1->ceilinglight->disableLight();
    room1->curtainlights->enableLight();
    If the 'frontlight' and so have a reference to the class of which they are member, events can be triggered when a light status changes if this is necessary.
    This changes nothing really. You still have to be able to know that some object has a "frontlight", "ceilinglight" and "curtainlight" members and that some other has none of them. The point is to have a common base class and then say "if this object has a ceiling light, turn it on". For that you can use double dispatch.

    Or in terms of C++:
    Qt Code:
    1. class Visitor {
    2. public:
    3. virtual void visitLivingRoom(LivingRoom *) {};
    4. virtual void visitBike(Bike *) {};
    5. };
    6.  
    7. class Item {
    8. public:
    9. virtual void accept(Visitor &visitor) = 0;
    10. };
    11.  
    12. class LivingRoom : public Item {
    13. public:
    14. void accept(Visitor &visitor) { visitor.visitLivingRoom(this); }
    15. };
    16.  
    17. class Bike : public Item {
    18. public:
    19. void accept(Visitor &visitor) { visitor.visitBike(this); }
    20. };
    To copy to clipboard, switch view to plain text mode 

    And then:

    Qt Code:
    1. class TurnLightsOnBikes : public Visitor {
    2. public:
    3. void visitBike(Bike *bike) { bike->turnLightsOn(); }
    4. };
    5.  
    6.  
    7. QList<Item*> items = ...
    8. TurnLightsOnBikes bVisitor;
    9. foreach(Item *item, items) {
    10. item->accept(bVisitor);
    11. }
    To copy to clipboard, switch view to plain text mode 

    Since C++ doesn't have double dispatch (only single dispatch through virtual methods) it has to be emulated like in the code above. Furthermore the visitor can be made a friend of Item subclasses to allow access to private members.

    In the "adding more lights" case it is enough to modify the visitor or create a new one. When a new subclass of Item is added, it is enough to add a new method to the Visitor interface. In all cases the Item class API remains clean and functionality is added by implementing a new Visitor subclass (which gives a nice separation and extendability).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  21. #18
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    Phlucious: I'm not a programmer by training, so I'm unfamiliar with some of the lingo.
    Wysota, I think we've lost someone in the discussion here..

    Maybe my example with the bike and chamber didn't really fit the OP's original problem. That's the danger of an OP asking a generic question without a real-life example. And that's also the danger for a replier of using a counter-example that is taken in other directions then intended.

    Anyway, what I mean to say is that OOP techniques aren't necessarely ALWAYS the best techniques for handling a problem. Especially for a novice. Can we agree on that ?

    Thanks for the pointer to the 'visitor' pattern. Didn't know that, will study it in more detail.

    Regards,
    Marc

  22. #19
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Defining shared class member functions only once

    Quote Originally Posted by marcvanriet View Post
    Anyway, what I mean to say is that OOP techniques aren't necessarely ALWAYS the best techniques for handling a problem. Especially for a novice. Can we agree on that ?
    I think multiple inheritance is a viable approach here.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  23. #20
    Join Date
    Aug 2009
    Location
    Belgium
    Posts
    310
    Thanks
    10
    Thanked 31 Times in 25 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: Defining shared class member functions only once

    OK, you win

Similar Threads

  1. Replies: 5
    Last Post: 26th September 2011, 09:12
  2. Pointer to non static member functions within the class
    By Lykurg in forum General Programming
    Replies: 3
    Last Post: 24th April 2011, 07:37
  3. how to document classes and member functions?
    By jackal in forum Qt Programming
    Replies: 15
    Last Post: 9th April 2011, 22:02
  4. Replies: 1
    Last Post: 16th March 2011, 08:10
  5. Pointers to Member Functions
    By Doug Broadwell in forum General Programming
    Replies: 8
    Last Post: 15th May 2007, 23:08

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.