-2

I do not know if this is possible or even if it should be done. Can i keep my .hpp files strictly interface without including source when using a base class with virtual functions? Here is the learning/test code I would like to change to work this way. Address is the base class with inheritance into classes EmailAddress and WebAddress.

address.cpp:

#include <string>
#include "address.hpp"

address.hpp:

#include <string>

#ifndef ADDRESS_HPP_
#define ADDRESS_HPP_

class Address {
public:
    virtual ~Address(){}
    virtual std::string to_string() const = 0;
};

#endif // ADDRESS_HPP_

emailaddress.cpp:

#include <string>
#include "emailaddress.hpp"
#include "address.hpp"

EmailAddress::EmailAddress(const EmailAddress& rhs) : _email(rhs._email) {}
EmailAddress::EmailAddress(std::string e) : _email(e) {}
EmailAddress& EmailAddress::operator=(const EmailAddress& rhs){
    if (&rhs != this) {
        _email = rhs._email;
    }
    return *this;
}

emailaddress.hpp:

#include <string>
#include "address.hpp"

#ifndef EMAILADDRESS_HPP_
#define EMAILADDRESS_HPP_

class EmailAddress : public Address {
public:
    EmailAddress() {}
    EmailAddress(const EmailAddress&);
    EmailAddress(std::string);
    virtual ~EmailAddress(){}
    EmailAddress& operator=(const EmailAddress&);
    std::string to_string() const override { return _email; }
private:
    std::string _email;
};
#endif // EMAILADDRESS_HPP_

webaddress.cpp:

#include <string>
#include "webaddress.hpp"
#include "address.hpp"

WebAddress::WebAddress(const WebAddress& rhs) : _uri(rhs._uri) {}
WebAddress::WebAddress(std::string e) : _uri(e) {}
WebAddress& WebAddress::operator=(const WebAddress& rhs){
    if (&rhs != this) {
        _uri = rhs._uri;
    }
    return *this;
}

webaddress.hpp:

#include <string>
#include "address.hpp"

#ifndef WEBADDRESS_HPP_
#define WEBADDRESS_HPP_

class WebAddress : public Address {
public:
    WebAddress() {}
    WebAddress(const WebAddress&);
    WebAddress(std::string);
    virtual ~WebAddress(){}
    WebAddress& operator=(const WebAddress&);
    std::string to_string() const override { return _uri; }
private:
    std::string _uri;
};

#endif // WEBADDRESS_HPP_

main.cpp:

#include <string>
#include <memory>
#include <iostream>
#include "address.hpp"
#include "emailaddress.hpp"
#include "webaddress.hpp"

void print_address(std::shared_ptr<Address> a) {
    std::cout << "address: " << a->to_string() << std::endl;
}

int main(int argc, char* argv[]) {
    std::shared_ptr<Address> s(new WebAddress("www.google.com"));
    print_address(s);

    std::shared_ptr<Address> s2(s);
    print_address(s2);

    std::shared_ptr<Address> s3 = s;
    print_address(s3);

    s.reset(new EmailAddress("john.doe@gmail.com"));
    print_address(s);

    s2.reset(new EmailAddress("john.doe@gmail.com"));
    print_address(s2);

    s3 = s;
    print_address(s3);

    return 0;
}
mszlazak
  • 59
  • 1
  • 6
  • 1
    What is your problem? The only declared virtual functions are dtors, but you never implemented them... – Jean-Baptiste Yunès Jun 17 '16 at 20:53
  • Good question. I am using a online video tutorial and dtors is not even mentioned. It has lost me since i tried changing the example hpp files to not include source code. – mszlazak Jun 18 '16 at 02:05
  • You address.hpp file appears to be an accidental copy of webaddress.cpp. I suspect the question will become clearer to us if you include your actual address.hpp file. (I'm guessing that's where some of your virtual declarations are). – define cindy const Jun 18 '16 at 03:06
  • Sorry about that. I have corrected address.hpp content and added the address.cpp and main.cpp files as well. – mszlazak Jun 18 '16 at 17:45
  • Updated code as asked. Please check – mszlazak Jun 18 '16 at 18:53

2 Answers2

2

Can i keep my .hpp files strictly interface without including source when using a base class with virtual functions?

yes, you can separate declaration and definition of virtual functions into header and implementation files.

m.s.
  • 16,063
  • 7
  • 53
  • 88
0

Doing this seemed to work. What hung me up before was the virtual specifier "override" being outside the class definition and being placed in the .cpp file. Here are the update emailaddress files that seem to now work:

emailaddress.hpp

#include <string>
#include "address.hpp"

#ifndef EMAILADDRESS_HPP_
#define EMAILADDRESS_HPP_

class EmailAddress : public Address {
public:
    EmailAddress() {}
    EmailAddress(const EmailAddress&);
    EmailAddress(std::string);
    virtual ~EmailAddress(){}
    EmailAddress& operator=(const EmailAddress&);
    std::string to_string() const override;
private:
    std::string _email;
};
#endif // EMAILADDRESS_HPP_

emailaddress.cpp

#include <string>
#include "emailaddress.hpp"
#include "address.hpp"

EmailAddress::EmailAddress(const EmailAddress& rhs) : _email(rhs._email) {}
EmailAddress::EmailAddress(std::string e) : _email(e) {}
EmailAddress& EmailAddress::operator=(const EmailAddress& rhs){
    if (&rhs != this) {
        _email = rhs._email;
    }
    return *this;
}
std::string EmailAddress::to_string() const { return _email; }
mszlazak
  • 59
  • 1
  • 6