2017-04-26 10 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];   
    } 

    // ... 
}; 

당신은 입력 배열 등, null의 경우 nAtoms가 0 또는 음수 있는지 확인하는 것이 필요 했어,하지만 난 FAL을 생각한다 질문의 범위를 벗어났습니다.

원시 포인터에 액세스해야하는 경우 positions.get() 메서드를 사용할 수 있습니다 (삭제하려고 시도하지 마십시오. 그렇지 않으면 응용 프로그램이 이중 삭제로 인해 충돌합니다). 당신은 원시 포인터에 액세스해야하는 경우에는합니다 (positions.data() 방법을 사용할 수 있습니다

#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];  
    } 

    // ... 
}; 

)

업데이트 물론

, 다른 더 간단한 해결책은 대신 std::vector<double>을 사용하는 것입니다 삭제를 시도하지 마십시오. 그렇지 않으면 응용 프로그램이 이중 삭제로 인해 충돌합니다. 원자 수는 positions.size()을 사용하여 확인할 수 있습니다.

덧글에서 언급했듯이 Atoms 클래스의 유일한 목적은 복식을 저장하는 것이지만 다른 작업을 추가하는 것이 아니라면 그냥 잊어 버리고 std::vector<double>을 직접 사용하십시오.