Преобразовать объект в указатель на объект? - PullRequest
0 голосов
/ 22 мая 2018

У меня есть следующее в C ++:

#ifndef INTERFACE_H
#define INTERFACE_H
class Interface {
public:
        virtual void blah() = 0;
};
#endif

#ifndef USER_H
#define USER_H

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

class User {
public:
        void callBlah(Interface* ptr) {
                ptr->blah();
        }
};
#endif

И у меня есть этот файл интерфейса SWIG:

%module(directors="1") interface

%{
#include "Interface.h"
#include "User.h"
%}

%feature("director") Interface;
%include "Interface.h"
%include "User.h"

И я скомпилировал:

$ swig -Wall -c++ -python -I/usr/include/python3.6m interface.i 
Interface.h:3: Warning 514: Director base class Interface has no virtual destructor.
$ g++ -shared -fPIC -I/usr/include/python3.6m Foo.cpp interface_wrap.cxx -o _interface.so

ТогдаЯ запустил:

import interface

class Implementation(interface.Interface):
    def __init__(self):
            super().__init__()
            self.__something = 1
    def blah(self):
            print("called python version")

i = Implementation().__disown__
u = interface.User()
u.callBlah(i)

И это дало:

Traceback (most recent call last):
  File "test.py", line 12, in <module>
    u.callBlah(i)
  File "/home/foo/test/swig/interface.py", line 142, in callBlah
    return _interface.User_callBlah(self, ptr)
TypeError: in method 'User_callBlah', argument 2 of type 'Interface *'

Таким образом, основная проблема заключается в том, что переменная i является объектом реализации (который реализовал интерфейс), но User :: callBlah() ожидает, что параметр является указателем на интерфейс.

Мой вопрос заключается в том, как преобразовать i в указатель на реализацию / интерфейс без изменения кода C ++?

Спасибо!

1 Ответ

0 голосов
/ 22 мая 2018

Просто взглянув на эту часть вашего кода:

#ifndef INTERFACE_H
#define INTERFACE_H
class Interface {
public:
        virtual void blah() = 0;
};
#endif

У вас есть класс, который имеет чисто виртуальный метод.Это означает, что вы не можете создать объект типа интерфейс напрямую, он не сможет скомпилироваться, если используется.Это означает, что вы должны наследовать от этого класса, а все классы, наследующие от этого класса, должны реализовывать функцию blah().Кроме того, поскольку вы наследуете от чисто виртуального абстрактного базового класса, у вас также должен быть virtual destructor.

. Вы можете сделать это:

#ifndef INTERFACE_H
#define INTERFACE_H

class Interface {
public:
    virtual ~Interface();
    virtual void blah() = 0;
};

#endif 

#ifndef INTERFACE_IMPL
#define INTERFACE_IMPL

class InterfaceImpl : public Interface {
public:
    InterfaceImpl() {}
    virtual ~InterfaceImpl(){}

    virtual void blah() override { /* implementation of blah here; */ }
};

#endif

Тогда какой исходный код использует Interface напрямую замените его либо InterfaceImpl, либо указателем на тип Inteface.Если вы используете более позднюю версию, вам придется выполнить кастинг между base и child class.

...