2017-04-26 86 views
2

我正在試圖創建一個指向類對象的void指針,並在函數內初始化它。不幸的是,類的數組成員不能轉義該函數,即它在初始化後不能被訪問。Void指向類對象的指針:函數內部的初始化

在下面的代碼中,第一次調用打印位置(在初始化函數內部)可以正常工作,但是,第二次調用從初始化函數外部打印位置失敗。我有一種感覺,在初始化函數中創建的數組對象被銷燬並且不會傳遞,但我不確定,也不知道如何解決它。

任何幫助將不勝感激。

#include <iostream> 
#include <iomanip> 
#include <string> 


class Atoms 
{ 
    double * positions; 
    int nAtoms; 

    public: 
     // Standard constructor prividing a pre-existant array 
     Atoms(int nAtoms, double * positionsArray) 
     { 
      this->nAtoms = nAtoms; 
      this->positions = positionsArray; 
     } 

     // Print positions to screen 
     void print_positions() 
     { 
      std::cout<< "nAtoms: " << this->nAtoms << std::endl; 
      int nDim = 3; 
      for (int i = 0; i < nAtoms; i++) 
      { 
       for (int j = 0; j < nDim; j++) 
       { 
        std::cout << std::setw(6) << this->positions[i * nDim + j] << " "; 
       } 
       std::cout << std::endl; 
      } 
      std::cout << std::endl; 
     } 

}; 


void initialize_Atoms_void_pointer(void ** voidAtomsPointer) 
{ 
    //Create a new instance of Atoms by a pointer 
    int numAtoms = 5; 
    int numDim = 3; 
    int elemN = numAtoms * numDim; 
    double data_array[elemN]; 

    for (int i = 0; i < numAtoms; i++) 
    for (int j = 0; j < numDim; j++) 
    { 
     data_array[i * numDim + j] = i * numDim + j + 10; 
    } 
    Atoms *atoms = new Atoms(numAtoms, data_array); 

    // Set the vPointer that the void pointer points to a pointer to Atoms object 
    *voidAtomsPointer = static_cast<void *>(atoms); 

    //Test call 
    std::cout << std::endl << "Initializing atoms" << std::endl; 
    static_cast<Atoms *>(*voidAtomsPointer)->print_positions(); 
} 


void print_Atoms_pointer_positions(void * voidAtomsPointer) 
{ 
    //Cast the pointer as an atoms pointer 
    Atoms *atomsPointer = static_cast<Atoms *>(voidAtomsPointer); 

    atomsPointer->print_positions(); 
} 

int main() 
{ 
    //Use the initializer function for getting a pointer 
    void *testVoidAtomsPointer; 

    initialize_Atoms_void_pointer(&testVoidAtomsPointer); 
    print_Atoms_pointer_positions(testVoidAtomsPointer); 
} 
+2

除了作爲本地核心問題的數組之外,另一個問題是'elemN'不是一個編譯時常量表達式,所以將它用作數組大小是不合適的。這很容易通過添加'const'來解決。 – user2079303

+0

'new','void *'。即使C++ 98有'std :: vector',C++ 11也引入了'std :: shared_ptr <>'。這段代碼真的很痛苦,因爲它重新發明了輪子,很糟糕。 – MSalters

+0

感謝您的建議。不幸的是,在這個問題中,我受到限制只能使用非常基本的工具。 –

回答

4

的問題是,在

Atoms *atoms = new Atoms(numAtoms, data_array); 

data_array是一個局部陣列,其被破壞時initialize_Atoms_void_pointer退出。

而是複製原始的指針,使Atoms的構造新的分配和複製內容:

Atoms(int nAtoms, double * positionsArray) 
{ 
    this->nAtoms = nAtoms; 
    this->positions = new double[nAtoms]; 
    for (int ii = 0; ii < nAtoms; ++ii) 
    this->positions[ii] = positionsArray[ii]; 
} 

~Atoms() 
{ 
    delete[] this->positions; 
} 

一個更安全的實現將包括使用std::unique_ptr的,它會自動解除分配內存支持你Atoms被破壞:

#include <memory> 

class Atoms { 
    std::unique_ptr<double[]> positions; 
    // ... 

public: 
    Atoms(int nAtoms, double * positionsArray) : 
    positions(new double[nAtoms]) { 
    this->nAtoms = nAtoms; 
    for (int ii = 0; ii < nAtoms; ++ii) 
     this->positions[ii] = positionsArray[ii];   
    } 

    // ... 
}; 

你最好也需要檢查,如果nAtoms爲0或負,如果輸入數組爲null,等等,但我認爲這FAL超出了問題的範圍。

如果您需要訪問原始指針,您可以使用positions.get()方法(不要嘗試刪除它或者您的應用程序將因雙重刪除而崩潰)。

更新

當然,另一個更簡單的解決辦法就是使用一個std::vector<double>代替;)

#include <vector> 

class Atoms { 
    std::vector<double> positions; 
    // int nAtoms; -- no longer necessary 

public: 
    Atoms(int nAtoms, double * positionsArray) : 
    positions(nAtoms) { 
    for (int ii = 0; ii < nAtoms; ++ii) 
     this->positions[ii] = positionsArray[ii];  
    } 

    // ... 
}; 

如果您需要訪問原始的指針,你可以使用positions.data()方法(不要試圖刪除它,否則你的應用程序將因雙重刪除而崩潰)。原子的數量可以使用positions.size()進行檢查。

正如在評論中提到的那樣,如果Atoms類的唯一目的是存儲雙打,但不添加任何其他操作,那麼就忘掉它並直接使用std::vector<double>