C++ 基类使用派生类的成员初始化会发出警告"uninitialized field"



我使用一个基类(a)来管理一些数据,但没有存储空间。派生类(B)有一个存储成员,并使用指向该存储的指针及其大小初始化基类(a)。

IDE中的代码模型(clang)给了我一个警告"字段mStorage在这里使用时未初始化"行explicit B() : A(mStorage.data(), 10) {}

问题1:只要我不使用基类构造函数中的存储,这是一个问题吗?

问题2:如果这不会引起问题,有没有办法避免这个警告?

class A
{
public:
explicit A(int* p, size_t s)
: mPtr(p), mSize(s)
{}
void append(int i) { /* ... */ }
private:
int*   mPtr  = nullptr;
size_t mSize = 0;
};

template <size_t N>
class B : public A
{
public:
explicit B() : A(mStorage.data(), N) {}
private:
std::array<int, N> mStorage {};
};

更新:

  • add template<到B类>
  • 我的意图是解耦类的正常使用和类B中的模板大小
void worker_function(const A& a)
{
a.append(int(1));
}
// and also
struct Foo
{
Foo(const A& a) : m_a(a) {}
void do_some_work()
{
a.append(int(1));
}
const A& m_a;
}; 
void main()
{
B<10> b;
worker_function(b);
// and also
Foo foo(b);
foo.do_some_work();
}

这个可能按您的意愿工作,但是编译器警告不应该被忽略。在A被构造的时候,mStorage还不存在。首先构造基类。也许编译器,看着mStorage,将提前窥视,可以这么说,但这不是所需的序列。mStorage可能只是随机的垃圾。

从框架中,很难猜测意图是什么,但是您可以通过创建一个虚函数来解决这个问题,该虚函数返回一个指向派生类中的存储的指针。您还可以找到某种模板解决方案。

我建议你多告诉我们一点你为什么要这样设计一个类。

更新:c++不知道N是多少是有原因的。当第(N+1)次调用worker_function时会发生什么?💥

我能想到两个更安全的方法。一种方法是使append成为一个(纯?)虚函数。无论如何,编写A::append并不容易,更不用说避免范围错误了。另一种方法是在A类中使用std::vector而不是std::array,而不尝试这种奇特的派生方案。

您可以使用组合而不是继承,并将类按正确的顺序排列。

请注意,我必须对你的constness做一些改动才能使它实际工作。

示例在此。

#include <array>
#include <cstddef>
class A
{
public:
explicit A(int* p, size_t s)
: mPtr(p), mSize(s)
{}
void append(int i) { mPtr[i] = i; ++i; } // My guess
private:
int*   mPtr  = nullptr;
size_t mSize = 0;
};

template <size_t N>
class B
{
public:
explicit B() : m_a(mStorage.data(), N) {}
operator A&() {
return m_a;
}
private:
std::array<int, N> mStorage {};
A m_a;
};

void worker_function(A& a)
{
a.append(int(1));
}
// and also
struct Foo
{
Foo(A& a) : m_a(a) {}
void do_some_work()
{
m_a.append(int(1));
}
A& m_a;
}; 
int main()
{
B<10> b;
worker_function(b);
// and also
Foo foo(b);
foo.do_some_work();
}

相关内容

最新更新