You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

当类成员来自其他类时如何实现构造函数?以Stack与Array类为例

Hey, great question! When you're building a class (like your Stack) that relies on another class (Array<T>) as a member variable, the core trick is using constructor initializer lists—they’re not just more efficient, but often mandatory if the member class doesn’t have a default constructor. Let’s break this down with your Array/Stack example, covering all common scenarios:

1. First, let’s define a simplified Array<T> template to work with

Before we dive into Stack, here’s a minimal Array<T> implementation (with common constructors) so our examples make sense:

template <typename T>
class Array {
private:
    T* data;
    size_t size;
public:
    // Default constructor: empty array
    Array() : data(nullptr), size(0) {}

    // Constructor with explicit size
    explicit Array(size_t sz) : size(sz) {
        data = new T[sz](); // Value-initialize elements
    }

    // Copy constructor: duplicate another array
    Array(const Array& other) : size(other.size) {
        data = new T[size];
        for (size_t i = 0; i < size; ++i) {
            data[i] = other.data[i];
        }
    }

    // Move constructor: take ownership of another array's resources
    Array(Array&& other) noexcept : data(other.data), size(other.size) {
        other.data = nullptr;
        other.size = 0;
    }

    // Destructor: clean up memory
    ~Array() {
        delete[] data;
    }

    // Helper: get current size
    size_t getSize() const { return size; }

    // Operator to access elements
    T& operator[](size_t idx) { return data[idx]; }
    const T& operator[](size_t idx) const { return data[idx]; }
};
2. Basic Stack constructor: Initialize Array with a fixed capacity

If you want your Stack to start with a default capacity (say, 10 elements), you’ll initialize the Array<T> member directly in the initializer list, along with your stack-top tracker:

template <typename T>
class Stack {
private:
    Array<T> arr;       // Our Array member
    size_t topIndex;    // Tracks the next empty position in the stack

public:
    // Default constructor: create Array with capacity 10, stack starts empty
    Stack() : arr(10), topIndex(0) {}
};

Why initializer list? This directly calls Array<T>’s Array(size_t sz) constructor for arr. If we tried to assign arr = Array<T>(10) inside the constructor body, it would first default-construct arr (wasting time/memory) then overwrite it—initializer lists avoid that overhead.

3. Stack constructor that accepts a custom capacity

If you want users to specify the stack’s initial capacity, just pass the parameter through to the Array<T> constructor in the initializer list:

template <typename T>
class Stack {
private:
    Array<T> arr;
    size_t topIndex;

public:
    // Explicit constructor: let user set initial capacity
    explicit Stack(size_t capacity) : arr(capacity), topIndex(0) {}
};

The explicit keyword prevents accidental implicit conversions (like Stack<int> s = 5;), which is a good practice for single-argument constructors.

4. Initialize Stack with an existing Array

If you want to build a stack from a pre-existing Array<T> (either copying or moving its data), use the initializer list to call Array<T>’s copy/move constructor:

template <typename T>
class Stack {
private:
    Array<T> arr;
    size_t topIndex;

public:
    // ... previous constructors ...

    // Copy constructor: duplicate an existing Array into the stack
    Stack(const Array<T>& existingArray) : arr(existingArray), topIndex(0) {}

    // Move constructor: take ownership of a temporary Array's resources (no copy!)
    Stack(Array<T>&& tempArray) noexcept : arr(std::move(tempArray)), topIndex(0) {}
};

The std::move here tells the compiler to use Array<T>’s move constructor instead of copy—perfect for when you’re passing a temporary array (like Stack<int> s = Array<int>(20);).

Key Notes to Remember
  • Always use initializer lists for member classes: If Array<T> didn’t have a default constructor, you’d get a compile error if you tried to initialize arr inside the constructor body instead of the initializer list.
  • Leverage the member class’s constructors: Your Stack constructor doesn’t need to reinvent the wheel—just pass the right arguments to Array<T>’s existing constructors.
  • Think about resource management: If Array<T> handles its own memory (like our example), Stack doesn’t need to do extra work—just let Array<T>’s destructor clean up when Stack goes out of scope.

内容的提问来源于stack exchange,提问作者nos28

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:03:03