Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Ran across this question today:

write a class Tool which will have a function void type() that every derived class should implement . A function Action() that every derived class can override . function init() which is available to only Tool and variable Name which will tell which class`s instance is this object

Here is my solution (based on other solutions I've found):

#include <typeinfo>

  class Tool{

      public:
           string name;
           Tool() {
                 name = typeid(*this).name(); 
           };

           virtual void type() = 0; 
           virtual void Action();   

      private:
           void init();  
  };

Could someone double check this please?

share|improve this question
2  
One minor thing I noticed is that you don't include std::string –  Caesar Nov 12 '12 at 22:16
add comment

4 Answers 4

up vote 4 down vote accepted

I would strongly recommend making name field const. Also, typeid(*this).name() won't look nice and pretty in some compilers. You should probably try something like:

class Tool {
public:
  const std::string name;
  <...>
protected:
  Tool(const char* className) : name(className) {}
private:
  <...>
}

BTW, do NOT expect typeid(*this).name(); to be called for deriven object. Even virtual functions won't help, so you can't write something like virtual const char* getMyName() = 0;, because any kind of "virtual" behavior will not work in constructor.

share|improve this answer
add comment

I suggest adding virtual destructor. Your polymorphic class can be used threw the pointer to the base class:

Tool* base = new Derived();
delete base;     // virtual destructor is required here

As suggested by @random-guy-from-internets, it is worth adding constructor which gets human-readable type name parameter. I'd suggest only to make it explicit:

class Tool {
public:
  virtual ~Tool() {}
protected:
  explicit Tool(const char* className) : name(className) {}
private:
  <...>
};
share|improve this answer
add comment

You can use templates to know what is the derived class:

#include <typeinfo>
#include <string>

class ToolBase {
  public:
       std::string name;
       explicit ToolBase(const std::string& classname):name(classname){}
       virtual ~ToolBase() {}
       virtual void type() = 0; 
       virtual void Action() {}
  private:
       void init(); 
};

template <typename Child>
class Tool : public ToolBase {
  public:
       Tool():ToolBase(typeid(Child).name()){}
};

And you use it like this:

class Derived : public Tool<Derived>
{
  public:
      Derived() {}
      ~Derived() {}
      void type(){
         //implementation could call Action
         Action();
      }
};
share|improve this answer
add comment

Your code does not work: http://codepad.org/OtKa9Aki

Just like calls to virtual functions in a constructor call the base class function, such usage of typeid also does not recognise the derived class. You could have the Tool constructor take an std::string and assign that to name.

Alternatively, you could be pedantic and claim that the instance of B will always be an instance of B, and that the derived classes are simply accessing this instance when they do d.name. I doubt, however, that this would be appreciated.

share|improve this answer
    
Not really sure what you mean by have the Tool constructor take an std::string and assign it to name. The problem wants the variable name to hold the name of the class - I don't think we're allowed to pass anything into the constructor. –  John Roberts Nov 13 '12 at 1:47
    
If you cannot pass anything to the constructor, what you are being asked to do is not possible. As you can see, calling typeid does not give the desired result. –  Anton Golov Nov 13 '12 at 11:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.