CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Nov 2016
    Posts
    7

    Unhappy Class templates inheritance

    Hi. I'm new. I try to create abstract database class Db and derived class Pg to handle at least connection to the database. I have private property with database connection type and because it will be unique depending on database I should implement templates.

    Code:
    #include <iostream>
    #include <postgresql/libpq-fe.h>
    
    using namespace std;
    
    template <class T>
    class Db 
    {
    public:
        Db(string, string, string, string);
        Db();
        string getHost();
        string getUsername();
        string getDatabase();
        string getPassword();
        virtual string getConnectionString()=0;
        virtual ~Db();
    
    protected: 
        T* m_conn;
        string m_host;
        string m_username;
        string m_database;
        string m_password;
    };
    
    template <class T>
    class Pg : public Db<T> {
    public:
        Pg(string, string, string, string);
        Pg();
        virtual ~Pg();
        virtual string getConnectionString();
    };
    
    template <class T>
    string Db<T>::getHost() {
        return m_host;
    }
    
    // ---------------------------------------------------------------------
    // username, database and password getters are implementing the same way
    // ---------------------------------------------------------------------
    
    template <class T>
    Pg<T>::Pg(string host, string username, string database, string password)
        // I intentionally remove Pg:: for m_host property
        : m_host(host), Pg::m_username(username), Pg::m_database(database), Pg::m_password(password) {
        Pg::m_conn = PQconnectdb(getConnectionString().c_str());
    
    	if (PQstatus(Pg::m_conn) == CONNECTION_BAD) {
    	    puts("Unable to connect to database");
    	    exit(0);
    	}
    }
    
    template <class T>
    string Pg<T>::getConnectionString() {
        return "host=" + this->getHost() + " user=" + this->getUsername()
            + " password=" + this->getPassword() + " dbname=" + this->getDatabase();
    }
    
    
    int main () {
    	Pg<PGconn> conn("localhost", "pg", "pg", "pwd");
    
    	return 0;
    }

    When I compile this beautiful code I get an errors:

    Code:
    load.cpp: In constructor ‘Pg<T>::Pg(std::string, std::string, std::string, std::string)’:
    load.cpp:50:7: error: class ‘Pg<T>’ does not have any field named ‘m_host’
         : m_host(host), Pg::m_username(username), Pg::m_database(database), Pg::m_password(password) {
           ^
    load.cpp: In instantiation of ‘Pg<T>::Pg(std::string, std::string, std::string, std::string) [with T = pg_conn; std::string = std::basic_string<char>]’:
    load.cpp:73:52:   required from here
    load.cpp:50:96: error: no type named ‘m_username’ in ‘class Pg<pg_conn>’
         : m_host(host), Pg::m_username(username), Pg::m_database(database), Pg::m_password(password) {
                                                                                                    ^
    load.cpp:50:96: error: no type named ‘m_database’ in ‘class Pg<pg_conn>’
    load.cpp:50:96: error: no type named ‘m_password’ in ‘class Pg<pg_conn>’
    As you can see if I remove Pg:: before m_host property I get the error that class does not have such field. If I place Pg:: before another connection properties I get the error no type named ‘m_database’.

    I completely stuck for two days with this issue.

    I use linux and g++ compiler:
    g++ -o load -g load.cpp -std=c++11 -lcurl -lpq

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,923

    Re: Class templates inheritance

    To initialise members of the base class, call a base class constructor eg

    Code:
    template <class T>
    Pg<T>::Pg(string host, string username, string database, string password)
    // I intentionally remove Pg:: for m_host property
    	//: m_host(host), Pg::m_username(username), Pg::m_database(database), Pg::m_password(password) {
    	: Db<T>(host, username, database, password) {
    ...
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Nov 2016
    Posts
    7

    Re: Class templates inheritance

    Thanks a lot, 2kaud! These errors disappear, but now I have another. Seems I don't understand the way inheritance work in C++:
    Code:
    /tmp/cc8AwHUL.o: In function `Pg<pg_conn>::Pg(std::string, std::string, std::string, std::string)':
    /home/arra/Projects/mudobot/rates/load.cpp:62: undefined reference to `Db<pg_conn>::Db(std::string, std::string, std::string, std::string)'
    collect2: error: ld returned 1 exit status

  4. #4
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,923

    Re: Class templates inheritance

    Based upon the code in post #1, the below compiles and executes. For test I've just set type PGconn to int

    Code:
    #include <string>
    #include <iostream>
    using namespace std;
    
    typedef int PGconn;
    
    template <class T>
    class Db
    {
    public:
    	Db(string h, string u, string d, string p) : m_host(h), m_username(u), m_database(d), m_password(p) {}
    	Db() {}
    	string getHost() const { return m_host; }
    	string getUsername() const { return m_username; }
    	string getDatabase() const { return m_database; }
    	string getPassword() const { return m_password; }
    	virtual string getConnectionString() const = 0;
    	virtual ~Db() {}
    
    protected:
    	T* m_conn = nullptr;
    	string m_host;
    	string m_username;
    	string m_database;
    	string m_password;
    };
    
    template <class T>
    class Pg : public Db<T> {
    public:
    	Pg(string, string, string, string);
    	Pg() {}
    	virtual ~Pg() {}
    	virtual string getConnectionString() const;
    };
    
    template <class T>
    Pg<T>::Pg(string host, string username, string database, string password)
    	: Db<T>(host, username, database, password) {
    
    	/*
    	if (PQstatus(Pg::m_conn) == CONNECTION_BAD) {
    		puts("Unable to connect to database");
    		exit(0);
    	}
    	*/
    }
    
    template <class T>
    string Pg<T>::getConnectionString() const {
    	return "host=" + getHost() + " user=" + getUsername()
    		+ " password=" + getPassword() + " dbname=" + getDatabase();
    }
    
    int main() {
    	Pg<PGconn> conn("localhost", "pg", "pg", "pwd");
    	cout << conn.getConnectionString() << endl;
    
    	return 0;
    }
    if your code is now different, it would be useful if you could post your revised code.
    Last edited by 2kaud; November 5th, 2016 at 07:20 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  5. #5
    Join Date
    Nov 2016
    Posts
    7

    Re: Class templates inheritance

    Great thanks!! I made it work with help of your better version of my code =)

    But one thing I don't understand is why should I add this-> anyway, because your version without this-> crashed with:
    Code:
    rates/load.cpp: In member function ‘virtual std::string Pg<T>::getConnectionString() const’:
    rates/load.cpp:55:63: error: there are no arguments to ‘getUsername’ that depend on a template parameter, so a declaration of ‘getUsername’ must be available [-fpermissive]
         return "host=" + this->getHost() + " user=" + getUsername()
    May be I forgot something from your version, thanks anyway. Here is the end working version:

    Code:
    #include <iostream>
    #include <vector>
    #include <string>
    #include <postgresql/libpq-fe.h>
    
    using namespace std;
    
    template <class T>
    class Db 
    {
    public:
        Db(string h, string u, string d, string p) 
    	    : m_host(h), m_username(u), m_database(d), m_password(p) {}
        Db() {}
        virtual ~Db() {}
        string getHost() const { return m_host; }
        string getUsername() const { return m_username; }
        string getDatabase() const { return m_database; }
        string getPassword() const { return m_password; }
        virtual string getConnectionString() const = 0;
    
    protected: 
        T* m_conn;
        string m_host;
        string m_username;
        string m_database;
        string m_password;
    };
    
    template <class T>
    class Pg : public Db<T> {
    public:
        Pg(string, string, string, string);
        Pg() {}
        virtual ~Pg() {}
        virtual string getConnectionString() const;
    };
    
    template <class T>
    Pg<T>::Pg(string host, string username, string database, string password)
        : Db<T>(host, username, database, password) {
        Pg::m_conn = PQconnectdb(getConnectionString().c_str());
    
    	if (PQstatus(Pg::m_conn) == CONNECTION_BAD) {
    	    puts("Unable to connect to database");
    	    exit(0);
    	}
    }
    
    template <class T>
    string Pg<T>::getConnectionString() const {
        return "host=" + this->getHost() + " user=" + this->getUsername()
            + " password=" + this->getPassword() + " dbname=" + this->getDatabase();
    }
    
    
    int main () {
    	Pg<PGconn> conn("a", "b", "c", "d");
    
    	cout << conn.getConnectionString() << endl;
    
    	return 0;
    }

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,923

    Re: Class templates inheritance

    Without the this-> in getConnectionString(), it works OK with MS VS2015. Sorry. I don't use the g++ compiler so can't comment on its error. Perhaps a guru who does use g++ can elaborate?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    Nov 2016
    Posts
    7

    Re: Class templates inheritance

    Strange thing. When I separate that code on files Db.h Pg.h and Pg.cpp I again get the error:
    Code:
    /tmp/ccCNyID2.o: In function `main':
    rates/load.cpp:71: undefined reference to `Pg<pg_conn>::getConnectionString() const'
    /tmp/ccCNyID2.o: In function `Pg<pg_conn>::Pg(std::string, std::string, std::string, std::string)':
    rates/../src/db/Pg.h:12: undefined reference to `Pg<pg_conn>::getConnectionString() const'
    /tmp/ccCNyID2.o:(.rodata._ZTV2PgI7pg_connE[_ZTV2PgI7pg_connE]+0x20): undefined reference to `Pg<pg_conn>::getConnectionString() const'
    collect2: error: ld returned 1 exit status
    It's really copy-paste, the difference only in head of the files where I do includes:
    Code:
    Pg.h: #include "Db.h"
    Pg.cpp: #include "Pg.h"
    main.cpp: #include "../src/db/Pg.h"

  8. #8
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,923

    Re: Class templates inheritance

    I suspect this is because you are splitting the class definition from its implementation (Pg.g and Pg.cpp). When templates are involved, the implementation is usually in the same unit as its definition (often a .hpp file).
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  9. #9
    Join Date
    Nov 2016
    Posts
    7

    Re: Class templates inheritance

    Thank you!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured