Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 [C++] Multiple Inheritance and the STL
Index -> Programming, C++ -> C++ Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
wtd




PostPosted: Sat Apr 09, 2005 12:52 am   Post subject: [C++] Multiple Inheritance and the STL

The goal

So, let's build a class which allows for the construction of simple HTML tags. Now, we'll be doing a lot of string concatenation, so we want something more efficient that constantly creating a lot of extra std::string objects. Fortunately the STL provides just such a thing in std::stringstream.

We'll only be putting things into a stringstream, so we can use std::ostringstream. We'll also want a way to keep track of which tag we're in, so a std::stack is also going to be needed.

First try

Let's take a first stab at it.

c++:
#include <string>
#include <sstream>
#include <stack>
#include <iostream>

using namespace std;

class tag_stream
{
   private:
      ostringstream stream;
      stack<string> current_tag;
   public:
      void start_tag(string tag_name);
      void end_tag();

      string str() const;

      template <typename _t>
      friend tag_stream& operator<<(tag_stream& ts, const _t& s);
};


And implementation:

c++:
void tag_stream::start_tag(string tag_name)
{
   current_tag.push(tag_name);
   stream << "<" << tag_name << ">";
}

void tag_stream::end_tag()
{
   stream << "</" << current_tag.top() << ">";
   current_tag.pop();
}

string tag_stream::str() const
{
   return stream.str();
}

template <typename _t>
tag_stream& operator<<(tag_stream& ts, const _t& s)
{
   ts.stream << s;
   return ts;
}


Now, you should notice that we're basically just duplicating the functionality that ostringstream possesses already, and a tag_stream is a ostringstream.

Single inheritance

We can simplify things a bit by just having tag_stream be a subclass of ostringstream.

c++:
#include <string>
#include <sstream>
#include <stack>
#include <iostream>

using namespace std;

class tag_stream : public ostringstream
{
   private:
      stack<string> current_tag;
   public:
      void start_tag(string tag_name);
      void end_tag();
};


And the implementation:

c++:
void tag_stream::start_tag(string tag_name)
{
   current_tag.push(tag_name);
   (*this) << "<" << tag_name << ">";
}

void tag_stream::end_tag()
{
   (*this) << "</" << current_tag.top() << ">";
   current_tag.pop();
}


Multiple inheritance

We're still working too hard, having that current_tag variable hanging around. But we shouldn't inherit from stack since a tag_stream isn't a stack, right? But, it sort of is a stack. But still, we don't want to be able to manipulate the stack from outside the class, so we can't inherit, right?

Ah, but we can. We simply use either private or protected inheritance. This type of inheritance also means that the program doesn't consider a tag_stream to be a stack.

c++:
#include <string>
#include <sstream>
#include <stack>
#include <iostream>

using namespace std;

class tag_stream : public ostringstream, protected stack<string>
{
   public:
      void start_tag(string tag_name);
      void end_tag();
};


And the implementation:

c++:
void tag_stream::start_tag(string tag_name)
{
   push(tag_name);
   (*this) << "<" << tag_name << ">";
}

void tag_stream::end_tag()
{
   (*this) << "</" << top() << ">";
   pop();
}


We wanted protected inheritance here because subclasses of tag_stream may want to directly manipulate the stack.

One last simplification

Since tag_stream has no private members, we can simply declare it as a struct. Also, we'll add a simple test.

c++:
#include <string>
#include <sstream>
#include <stack>
#include <iostream>

using namespace std;

struct tag_stream : public ostringstream, protected stack<string>
{
   void start_tag(string tag_name);
   void end_tag();
};

int main()
{
   tag_stream s;
   s.start_tag("html");
   s << "hello";
   s.end_tag();

   cout << s.str() << endl;   

   return 0;
}

void tag_stream::start_tag(string tag_name)
{
   push(tag_name);
   (*this) << "<" << tag_name << ">";
}

void tag_stream::end_tag()
{
   (*this) << "</" << top() << ">";
   pop();
}
Sponsor
Sponsor
Sponsor
sponsor
Martin




PostPosted: Sat Apr 09, 2005 8:07 pm   Post subject: (No subject)

I would highly recommend the book 'The C++ Standard Library' by Nicolai M. Josuttis for anyone who would like to learn more about the STL.
Display posts from previous:   
   Index -> Programming, C++ -> C++ Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 2 Posts ]
Jump to:   


Style:  
Search: