4

I am trying to get something like this to work:

int main()
{
    class Base
    {
    public:
        Base() = default;
        virtual void print() = 0;
        void CallThread()
        {
            std::thread(&Base::print, *this);
        };
    };

    class derived1 : public Base
    {
    public:
        derived1() = default;
        void print() { printf("this is derived1\n"); }

    };
    class derived2 : public Base
    {
    public:
        derived2() = default;
        void print() { printf("this is derived2\n"); }

    };
    Base* ptr;
    ptr = new derived1();
    ptr->CallThread();

    return 0;
}

The result I want to happen is :

this is derived1.

The problem is it won't even compile. I am using VisualStudio 2013.

The error is :

Error 2 error C3640: 'main::Base::[thunk]: __thiscall main'::2'::Base::`vcall'{0,{flat}}' }'' : a referenced or virtual member function of a local class must be defined

Any ideas how to make this work?

edit: just to be clear, what I'm trying to do in the thread is more complicated, this is just an example of the structure of my program (so lambda isn't a good idea for me)

3
  • 1
    Can't you just use a lambda? Commented Aug 29, 2014 at 13:01
  • 2
    Not sure on the error, but shouldn't std::thread(&Base::print, *this); be std::thread(&Base::print, this); so as to not create a copy of Base? Or was the copy intended? Commented Aug 29, 2014 at 13:06
  • 2
    @Niall You've identified the problem: you cannot create instances of abstract classes. std::thread(&Base::print, *this) tries to create a copy of Base for the thread. Either std::ref or a pointer is required. There's a lifetime problem once you use a pointer or reference, though. Also, the thread must be detached or joined, otherwise an exception will be thrown. Commented Aug 29, 2014 at 13:08

1 Answer 1

11

Your code is fine, except for two things:

std::thread(&Base::print, *this);

should be:

std::thread(&Base::print, this).join(); // join & no asterisk
Sign up to request clarification or add additional context in comments.

5 Comments

Locally defined classes need to have the member methods defined inside the class body (even if empty), so virtual void print() {} (for gcc and msvc). That said, I've learnt a whole lot of new things about local classes, here.
@Niall: you have mixed something, it's fine to have pure-virtual in local class, what you can't do is to have class A{void print();}; void A::print() {} locally
This seems to be a variation in implemementation between gcc and msvc. Local class must have the functions declared in the body, but you cannot have a pure specifier =0 and a definition together, so =0 {} would not be allowed. I did not know this... Msvc does accept the code with both the specifier and definition together thought, gcc doesn't.
This almost did the trick for me - but it still didn't work, I had to remove the pure specifier ( = 0 ) and just leave empty brackets on the overloaded print() function of Base class - and that worked.
@DorIoushua: §9.8.2: "Member functions of a local class shall be defined within their class definition, if they are defined at all."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.