Split class over 2 files

Discussion in 'C++' started by pkirk25, Oct 23, 2006.

  1. pkirk25

    pkirk25 Guest

    Hi,

    I want to create a class with its definition in cls.h and
    implementation in cls.cpp I get errors about redfinitions and errors
    wahtever way I try to initialise the static proivate variable
    *log_file.

    // cls.h:

    class logger
    {
    public:
    void create(char *log_file_name);
    };

    // cls.cpp
    class logger
    {
    public:
    void create(char *log_file_name)
    {
    srtcpy *log_file_name, *log_file);
    }
    private:
    static char *log_file;
    };

    What is the right way to split this so that compiler knows what I am
    trying to do?
     
    pkirk25, Oct 23, 2006
    #1
    1. Advertising

  2. pkirk25

    Daniel T. Guest

    In article <>,
    "pkirk25" <> wrote:

    > Hi,
    >
    > I want to create a class with its definition in cls.h and
    > implementation in cls.cpp I get errors about redfinitions and errors
    > wahtever way I try to initialise the static proivate variable
    > *log_file.
    >
    > // cls.h:
    >
    > class logger
    > {
    > public:
    > void create(char *log_file_name);
    > };
    >
    > // cls.cpp
    > class logger
    > {
    > public:
    > void create(char *log_file_name)
    > {
    > srtcpy *log_file_name, *log_file);
    > }
    > private:
    > static char *log_file;
    > };
    >
    > What is the right way to split this so that compiler knows what I am
    > trying to do?


    Put include guards in your header file.
    http://en.wikipedia.org/wiki/Include_guard

    --
    To send me email, put "sheltie" in the subject.
     
    Daniel T., Oct 23, 2006
    #2
    1. Advertising

  3. pkirk25

    Martin Steen Guest

    pkirk25 wrote:
    > Hi,
    >
    > I want to create a class with its definition in cls.h and
    > implementation in cls.cpp I get errors about redfinitions and errors
    > wahtever way I try to initialise the static proivate variable
    > *log_file.
    >
    > // cls.h:
    >
    > class logger
    > {
    > public:
    > void create(char *log_file_name);
    > };
    >
    > // cls.cpp
    > class logger
    > {
    > public:
    > void create(char *log_file_name)
    > {
    > srtcpy *log_file_name, *log_file);
    > }
    > private:
    > static char *log_file;
    > };
    >
    > What is the right way to split this so that compiler knows what I am
    > trying to do?



    Did you mean:

    void create(char* log_file_name)
    {
    strcpy(log_file, log_file_name);
    }

    This would copy the log_file_name into log_file.
    But until log_file is uninitialised, the code
    will crash.

    It's better to make log_file an array:

    char log_file[MAX_FILENAME_LENGTH];

    Even better: using std::string class for strings ;)

    Best regards,
    -Martin
     
    Martin Steen, Oct 23, 2006
    #3
  4. pkirk25

    Tom Smith Guest

    pkirk25 wrote:
    > Hi,
    >
    > I want to create a class with its definition in cls.h and
    > implementation in cls.cpp I get errors about redfinitions and errors
    > wahtever way I try to initialise the static proivate variable
    > *log_file.
    >
    > // cls.h:
    >
    > class logger
    > {
    > public:
    > void create(char *log_file_name);
    > };
    >
    > // cls.cpp
    > class logger
    > {
    > public:
    > void create(char *log_file_name)
    > {
    > srtcpy *log_file_name, *log_file);
    > }
    > private:
    > static char *log_file;
    > };
    >
    > What is the right way to split this so that compiler knows what I am
    > trying to do?
    >


    The reason you're getting errors about "redefinitions" is because you have
    indeed defined the class twice. You need to use a different syntax in the cpp
    file for implementing the class' member functions.

    I'm pretty certain you don't want log_file to be a static variable. (Do you?
    What static means in the context of a class is that every class shares that
    single variable - so in this case, every logger you create will automatically be
    writing to the same file.)

    The way you should split your code is like this:

    // cls.h

    class logger
    {
    public:
    void create(char *log_file_name)
    private:
    char *log_file;
    };

    // cls.cpp

    void logger::create(char *log_file_name)
    {
    srtcpy (*log_file_name, *log_file);
    }

    There are two significant issues with this code. The first is that you've used a
    char* to store text: this is very hard, and your code is buggy as a result.
    The first bug is that you're passing *log_file_name to the function strtcpy:
    this is the value _stored_ at the address log_file_name, and not the _actual
    address_, which is what it will certainly be expecting - there's the same thing
    with *log_file - to do that you would write srtcpy (log_file_name, log_file).

    However, this is still buggy: at the moment, log_file hasn't been initialised
    yet, and so doesn't point to anything - or rather, it probably points to some
    random piece of memory. This is very bad. I could show you how to sort this out
    as well, but in fact there's a much better solution: std::string, in the
    standard library, which handles all text processing much better and more easily
    than you or I could ever hope to do. Rewritten with std::string your code would
    look like this:

    // cls.h

    #include <string>

    using std::string;

    class logger
    {
    public:
    void create(string const& log_file_name)
    private:
    string log_file;
    };

    // cls.cpp

    void logger::create(string const& log_file_name)
    {
    // guarantees log_file gets its own bit of memory
    log_file = log_file_name.substr();
    }

    A good reference on strings can be found here:
    http://www.camtp.uni-mb.si/books/Thinking-in-C /Chapter01.html

    However, there's still more improvements. Have you studied constructors yet? A
    constructor is essentially a built-in create function. I won't go into detail
    here, but again Thinking in C++ is an excellent reference:
    http://www.camtp.uni-mb.si/books/C /Chapter06.html

    Rewritten with a proper constructor, your code becomes this:

    // cls.h

    #include <string>

    using std::string;

    class logger
    {
    public:
    logger()
    logger(string const& log_file_name)
    private:
    string log_file;
    };

    // cls.cpp

    logger::logger()
    : log_file ("default.log")
    {
    }

    logger::logger(string const& log_file_name)
    : log_file (log_file_name.substr());
    {
    }

    Having done that, you can now declare a new logger very straightforwardly:
    logger MyLogger("errors.log");

    This is quite a lot of information - hope some of it helps...

    Tom
     
    Tom Smith, Oct 23, 2006
    #4
  5. pkirk25 wrote:
    > Hi,
    >
    > I want to create a class with its definition in cls.h and
    > implementation in cls.cpp I get errors about redfinitions and errors
    > wahtever way I try to initialise the static proivate variable
    > *log_file.
    >
    > // cls.h:
    >
    > class logger
    > {
    > public:
    > void create(char *log_file_name);
    > };
    >
    > // cls.cpp
    > class logger
    > {
    > public:
    > void create(char *log_file_name)
    > {
    > srtcpy *log_file_name, *log_file);
    > }
    > private:
    > static char *log_file;
    > };


    I can't understand why you write code like that,you defined class
    logger twice
    Why not void logger::create

    >
    > What is the right way to split this so that compiler knows what I am
    > trying to do?

    ..
     
    Osamede Zhang, Oct 23, 2006
    #5
  6. pkirk25

    pkirk25 Guest

    Tom,

    Wow - thanks! I was completely messign it up.

    Mind if I pick your brain further?

    I want to have the logger class have a member function called write()
    that is overlaoded.

    write(char *file_name, string message)
    write(string message)

    I thought using the static term would mean that if I created an
    instance called myLog whcih writes to "new_log.html", any other class
    could append to the same logfile just by using the write(string
    message) function.

    A file name used by fstream shoudl be in the char *file_name format
    which is only reason I use it.

    What is best way to have the filename persist if static is not right?

    Patrick
     
    pkirk25, Oct 23, 2006
    #6
  7. pkirk25

    Salt_Peter Guest

    pkirk25 wrote:
    > Tom,
    >
    > Wow - thanks! I was completely messign it up.
    >
    > Mind if I pick your brain further?
    >
    > I want to have the logger class have a member function called write()
    > that is overlaoded.
    >
    > write(char *file_name, string message)
    > write(string message)


    the above are not functions, if you properly make them functions you
    can simply add them to your interface and implementation. Note that you
    don't need the first write since you have presumeably already loaded
    the filename using the def ctor or parametized ctor.

    // logger.h
    #ifndef LOGGER_H_
    #define LOGGER_H_ /*include guards */
    #include <string>

    class logger
    {
    std::string log_file;
    public:
    logger();
    logger(const std::string& log_file_name);
    void write(std::string& msg) const;
    };

    #endif /* LOGGER_H_ include guard */
    ___
    // cls.cpp
    #include "logger.h"
    using std::string;

    logger::logger() : log_file ("default.log")
    {
    }

    logger::logger(const string& log_file_name)
    : log_file (log_file_name);
    {
    }

    void logger::write(const string& msg) const
    {
    // do stuff here (ie: open a std::eek:fstream to log_file and << msg)
    }

    >
    > I thought using the static term would mean that if I created an
    > instance called myLog whcih writes to "new_log.html", any other class
    > could append to the same logfile just by using the write(string
    > message) function.


    Not neccessarily. Static means that the object persists in global space
    where *only* static functions can access static objects. That
    complicates your class's interfaces because you now would need a static
    function everywhere you want to access the static logger. Also, static
    does not mean persist accross compilation boundaries. You could very
    well end up with distinct loggers in seperate compilation units. You'ld
    have to make the logger static and extern(al). Why deal with such a
    mess?
    Imagine a static logger overhere writing to the same file as a logger
    overthere?
    You also want to consider the implications of having to "couple" your
    other classes.
    Where a bunch of objects rely on some static logger to be available in
    order for an instance of that class to do anything. It gets nasty.

    >
    > A file name used by fstream shoudl be in the char *file_name format
    > which is only reason I use it.


    a std::string variable can return a constant char* easily.

    std::string filename("log.txt");
    const char* = filename.c_str();

    >
    > What is best way to have the filename persist if static is not right?


    Instead of making it static, just initialize it in main and let main's
    scope "persist" it.

    #include "logger.h"

    int main()
    {
    logged thelog("log.txt");

    // do whatever including thelog.write( ... )
    // or let other objects take a reference to your logger
    // window.logit(thelog);

    } // thelog gets zapped here
     
    Salt_Peter, Oct 23, 2006
    #7
  8. pkirk25

    pkirk25 Guest

    Learnt a lot here - thanks all.
     
    pkirk25, Oct 24, 2006
    #8
    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. precious
    Replies:
    0
    Views:
    626
    precious
    May 22, 2004
  2. Replies:
    2
    Views:
    470
  3. Carlos Ribeiro
    Replies:
    11
    Views:
    702
    Alex Martelli
    Sep 17, 2004
  4. trans.  (T. Onoma)

    split on '' (and another for split -1)

    trans. (T. Onoma), Dec 27, 2004, in forum: Ruby
    Replies:
    10
    Views:
    218
    Florian Gross
    Dec 28, 2004
  5. Sam Kong
    Replies:
    5
    Views:
    246
    Rick DeNatale
    Aug 12, 2006
Loading...

Share This Page