0

I'm trying to create a class Animal, with some subclasses that have a interface method newObject() return new instance of self:

Animal.h

class Animal{
public:
    virtual Animal* newObject()=0;
};

and I am trying to implement registry pattern, with a class AnimalRegister, which stores mapping between class name and an instance of the class:

AnimalRegister.h

#include <map>
class Animal;
class AnimalRegister{
public:
    static void* add(const char* name,Animal* a);
    static Animal* get(const char* name);
protected:
    static std::map<const char*,Animal*> m;
};

AnimalRegister.cpp

#include "AnimalRegister.h"
#include <stdio.h>
std::map<const char*,Animal*> AnimalRegister::m;
void* AnimalRegister::add(const char* name,Animal* a){
    m[name]=a;
    printf("%s registered\n",name);
    return NULL;
}

Animal* AnimalRegister::get(const char* name){
    return m[name];
}

when I add a subclass Cat:

Cat.h

#include "Animal.h"
class Cat : public Animal{
public:
    virtual Animal* newObject();
protected:
    static void* Cat_;
};

Cat.cpp

#include "Cat.h"
#include <stdio.h>
#include "AnimalRegister.h"

void* Cat::Cat_=AnimalRegister::add("Cat",new Cat());
Animal* Cat::newObject(){
    printf("Cat::newObject");
    return new Cat();
}

the line

void* Cat::Cat_=AnimalRegister::add("Cat",new Cat());

maps the string "Cat" to instance of Cat, so that later I can create a new Cat by name:

Animal* a=AnimalRegister::get("Cat")->newObject();

instead of

if(string(name)=="Cat"){
    return new Cat();
}

that violates open closed principle when add a new subclass.

but when I try to test the code above:

#include "Cat.h"
#include "AnimalRegister.h"
int main(){
    printf("#1");
    Animal* a1=AnimalRegister::get("Cat");
    printf("#2");
    Animal* a2=a1->newObject();
    printf("#3");
};

the output is only:

Segmentation fault: 11

and seems never reaches the main,what is the reason?

ggrr
  • 7,737
  • 5
  • 31
  • 53
  • It is not relevant to your problem, but your function `AnimalRegister::add` always returns `NULL` shouldn't it return the `a`? I'm not sure I get what `Cat_` is for in the first place though :) – Tommy Andersen Jun 21 '16 at 08:21
  • Using `char*` as a map key is very error-prone. Stick to C++ and use `std::string`. – molbdnilo Jun 21 '16 at 08:22
  • 1
    @TommyAndersen It doesn't have to return anything, OP just thought this hack that allows him to call it outside a function was cool. It is not. – LogicStuff Jun 21 '16 at 08:27
  • 3
    Two string literals `"Cat"` are not guaranteed to have the same address - which is what your `AnimalRegister::get` requires. Forget C. – LogicStuff Jun 21 '16 at 08:34
  • you may find a solution in another post : http://stackoverflow.com/questions/42719249/how-to-implement-registry-pattern-in-c-using-single-registry-for-many-inter – Arcadien Mar 10 '17 at 15:28

1 Answers1

1

You are missing end of line character ("\n") on the prints. Segfault happens before you are outputting an end of line character and therefore nothing is printed. Try

printf("#1\n");

EDIT: As for why the segfault happens, get("Cat") returns a null pointer because you haven't called add("Cat"). The segfault comes from trying to call newObject on the nullpointer.

Lof
  • 113
  • 7
  • 3
    While nicely observed, probably more of a comment, than an answer. – Tommy Andersen Jun 21 '16 at 08:22
  • Sorry for this, didn't have enough points for comment. Does answer the question "never reaches main, what is the reason?" though. – Lof Jun 21 '16 at 11:09
  • The user didn't ask why the error happens, the question was why the program doesn't seem to reach main. Added an answer to the irrelevant question anyways. – Lof Jun 21 '16 at 15:38