C++ 类型转换基础 PTR 到派生 PTR 保存在引用类中

c++ typecast base ptr to derived ptr held in a reference class

本文关键字:PTR 存在 引用 保存 类型转换 C++ 派生      更新时间:2023-10-16

我正在尝试创建一个对象引用模板类,该模板类将保存类指针,并且除了尝试将强制基类 ptr 键入派生类 ptr 时,一切都可以正常工作。

这是代码:

#include <stdio.h>
#include <stdlib.h>
#define null nullptr
class BaseType;
class DerivedType;
template<class T>
class ObjRef {
public:
T *ptr = null;  //should be private
ObjRef& operator= (T *ptr) { this->ptr = ptr; return *this; }
ObjRef& operator= (const ObjRef &ref) { ptr = ref.ptr; return *this; }
operator T*() const {return ptr;}
operator T() const {return *ptr;}
ObjRef() {}
ObjRef(const ObjRef &copy) { ptr = copy.ptr; }
#ifdef VOID_FIX
ObjRef(void*p) { ptr = (T*)p; }  //this could fix the bug except would not work with multiple inheritance and is not safe
#else
ObjRef(T*p) { ptr = p; }
#endif
~ObjRef() { }
T* operator->() const {return ptr;}  //unfortunately operation. (dot) can not be overloaded - that would make life too easy :(
};
class Object {};
class BaseType : public Object {
public:
int baseValue;
};
class DerivedType : public BaseType {
public:
operator BaseType*() {return (BaseType*)this;}  //helpful?
int derivedValue;
};
typedef ObjRef<BaseType> Base;
typedef ObjRef<DerivedType> Derived;
void func4(Base x) {
x->baseValue = 1;
}
void func5(Derived x) {
x->derivedValue = 1;
}
int main() {
Base b = null;
Derived d = null;
Base x;
x = d;  //no type cast needed
func4((Base)d);  //cast from Derived to Base class - no problem
b = d;  //base does point to derived
//  func5((Derived)b);  //cast from Base to Derived - does not work (desired syntax)
// with gcc -fpermissive can be used to change error to warning - can I silence the warning ?
// what would cl.exe equivalent be?
//  func5((Derived)b.ptr);  //invalid cast, ptr should be private
//  func5((DerivedType*)b);  //invalid cast, ptr should be private
//  func5(dynamic_cast<DerivedType*>(b.ptr));  //invalid cast, source type is not polymorphic, ptr should be private
func5((DerivedType*)b.ptr);  //this works but is undesired and ptr should be private
func5(static_cast<DerivedType*>(b.ptr));  //works but again is undesired and ptr should be private
return 0;
}

在示例中 ObjRef<> 是一个模板,其中包含指向定义的类的指针,并用作新类型。 除了尝试将基类强制转换为派生类外,它工作正常。 看看如何使用基类引用调用func5((。第一次尝试是所需的语法。 如果我在参考类中使用 ptr,它将起作用,但这是不希望的。

我只是觉得我错过了一个操作员或其他东西。

谢谢。

像往常一样,我在发布后不久就找到了解决方案。
ObjRef<>类需要知道基类。 以下是新代码:

#include <stdio.h>
#include <stdlib.h>
#define null nullptr
class BaseType;
class DerivedType;
template<class T>
class ObjRef {
public:
T *ptr = null;
ObjRef& operator= (auto *ptr) { this->ptr = ptr; return *this; }
ObjRef& operator= (const ObjRef<auto> &ref) { ptr = ref.ptr; return *this; }
operator T*() const {return ptr;}
ObjRef() {}
ObjRef(const ObjRef<auto> &copy) { ptr = (T*)copy.ptr; }
ObjRef(T*p) { ptr = p; }
~ObjRef() { }
T* operator->() const {return ptr;}  //unfortunately operator. (dot) can not be overloaded - that would make life too easy :(
};
class Object {};
class BaseType : public virtual Object {
public:
int baseValue;
};
class InterfaceType : public virtual Object {
public:
virtual void func7() {
printf("it works!n");
};
};
typedef ObjRef<InterfaceType> Interface;
class DerivedType : public BaseType, public InterfaceType {
public:
int derivedValue;
};
typedef ObjRef<BaseType> Base;
typedef ObjRef<DerivedType> Derived;
void func4(Base x) {
x->baseValue = 1;
}
void func5(Derived x) {
x->derivedValue = 2;
}
void func6(Interface x) {
x->func7();
}
int main() {
Base b = new BaseType();
Derived d = new DerivedType();
Base x;
x = d;  //no type cast needed
func4((Base)d);  //cast from Derived to Base class - no problem
printf("BaseValue=%dn", d->baseValue);
b = d;  //base does point to derived
func5((Derived)b);  //cast from Base to Derived - works now!
printf("DerivedValue=%dn", d->derivedValue);
func6(d);
return 0;
}

更新:发布了一个新版本,该版本适用于任何级别的继承,但现在需要C++14(自动关键字(

更新 #2:现在使用单个 ObjRef 类(仍然需要 C++14(。 不幸的是,cl.exe 尚不支持"自动"模板参数:(

更新#3:添加了一些测试代码来证明它有效。