向 C++ 添加“扩展方法支持”的错误指针分配技巧将来会成为问题吗?

Can incorrect pointer assignment trick for add “Extension methods support” to C++ be a _problem in future?

我将用于向 JNI jobjects 添加“C++ 扩展方法”以使 NDK 代码更具可读性(如(统一函数调用语法))的解决方案是:

重载最小,我们可以访问原始 class 的 public 方法。

#include <iostream>

// Represents a class external to my source
class Person {
public:
    Person(){
        privateage = 20;
    }
    int age() { return privateage; }
private:
    int privateage;
    short anotherField;
};

class PersonExtensions : private Person {
public:
    inline int size() { return 5 + age(); }
    //NoFieldsOnExtensionClass
};

int main() {

    Person person;

    PersonExtensions* pE = (PersonExtensions*) &person;
    std::cout << pE -> size() << std::endl;
    std::cout << (*pE).size() << std::endl;

    std::cout << sizeof(Person) << std::endl;
    std::cout << sizeof(PersonExtensions) << std::endl;

    return 0;
}

你认为这个指针赋值不正确吗,因为“扩展方法”只访问了扩展 class 的 public 成员和扩展 class 不会有任何字段变量, 能代表未来的问题吗? 对象大小相同

非常感谢。

这是未定义的行为

是的,随时都可能崩溃。

考虑重载 ->* 或其他方法。

或者只是使用免费功能。

如果你真的想要中缀表示法:

template<class T, class F>
struct extension_method_t {
  F f;
  friend auto operator->*( T& t, extension_method_t const& self ) {
    return [&t,&self](auto&&...args)->decltype(auto) {
      return self.f( t, decltype(args)(args)... );
    };
  }
};
template< class T, class F >
extension_method_t<T,F> extension_method( F f ) {
  return {std::move(f)};
}

然后:

auto size = extension_method<Person>([](auto& person)->int{
  return 5+person.age();
});
Person p;
std::cout << (p->*size)() << "\n"; // prints p.age()+5

这里我们没有扩展方法,但是我们有一个扩展方法指针。

你在你的问题代码中所做的是未定义的行为,所以一个特别优化的编译器可能会用它做真正的"fun"事情。换句话说,不要这样做,即使您测试它可以工作,它也可能随时崩溃。确保它实际工作的唯一方法是在每次编译后检查生成的汇编代码,以确保它做你想做的,这基本上是不可能的,所以它永远不安全。


您正在使用私有继承。所以为了同样的效果,你可以这样做:

class PersonExtensions {
public:
    PersonExtensions(Person *person) : _person(person) {}
    inline int size() { return 5 + _person->age(); }
private:
    Person *_person;
};

如果您改为使用 public 继承(这样您就可以通过 PersonExtensions 调用 Person 方法),那么您需要为 _person(对于需要真实 Person 的情况),and/or 为 Person 方法添加委托(对于所谓的静态多态性)。