Search code examples
c++design-patternsfactoryfactory-pattern

Having trouble with inheritance in implementation of C++ factory method


Fairly new to design patterns, maybe I've missed the answered question already. I'm having trouble practicing the factory design pattern due to an inheritance issue.

This is the base class

 #ifndef FACTORY_H
 #define FACTORY_H

 #include <iostream>
 #include "truckfactory.h"

 class factory{

     public:
         std::string typeOfCar;
         factory(){}

         virtual void identifyCar(){
             std::cout << "This car is a " + typeOfCar << std::endl;
         }

         truckfactory* createTruck(){
             return new truckfactory();}
 };
 #endif

And this is the subclass of the base factory class.

 #ifndef TRUCKFACTORY_H
 #define TRUCKFACTORY_H

 #include "factory.h"
 class truckfactory : public factory{

     public:
         truckfactory(){
             std::cout <<"TruckFactory made"<<std::endl;
             typeOfCar = "truck";
         }   
 };
 #endif

Trying to implement as such

 #include "factory.h"

 int main(){

     factory carFactory;
     truckfactory* truck;
     truck = carFactory.createTruck();

     carFactory.identifyCar();
     truck->identifyCar();

     return 0;
 }

However I run into the following issues

./truckfactory.h:5:29: error: expected class name
class truckfactory : public factory
                            ^
./truckfactory.h:11:13: error: use of undeclared identifier 'typeOfCar'
            typeOfCar = "truck";
            ^
factorytest.cpp:10:12: error: no member named 'identifyCar' in 'truckfactory'
    truck->identifyCar();

I was looking around at other inheritance issues, but I couldn't find one that solves what I'm looking at.

Thanks for the help, and sorry if it's a repost


Solution

  • There are a few things to consider:

    1. The reason your code won't compile is due to its structure. You can't (or shouldn't) have factory.h include truckfactory.h, which then includes factory.h. The circular dependency will cause you problems. The normal way of handling this is to forward declare truck_factory like this:
     #ifndef FACTORY_H
     #define FACTORY_H
    
     #include <iostream>
    
    class truck_factory;
    
    class factory{
    
         public:
             std::string typeOfCar;
             factory(){}
    
             virtual void identifyCar(){
                 std::cout << "This car is a " + typeOfCar << std::endl;
             }
    
             truckfactory* createTruck(); //Note definition must be in c++ file
     };
     #endif
    
    1. Conceptually your factory should build objects, not other factories. For example, you might have a class factory which knows how to build trucks, car, motorbikes etc. To do this you would want to define a vehicle class and then a factory which can build the correct class based on the type passed in. Something like:
    class Vehicle {
       public:  
           virtual std::string typeOfCar() const = 0; 
           void identifyCar() {
                 std::cout << "This car is a " + typeOfCar << std::endl;
             }
    };
    
    class Factory { 
        public:
            Vehicle* create_vehicle(const std::string& type); // need to somehow specify what type you want to create.
    };
    
    class Truck : public Vehicle {
        virtual std::string typeOfCar() const { return "truck"; }
    };
    

    The create_vehicle function would need to be defined in a cpp file to return various vehicle types.