thắc mắc Cao thủ C++ cho em hỏi tý ạ.

Bạn chạy đoạn code này xem:
Code:
    int a = 10, b = 4;
    float thuong;
    thuong = (float) a/b;
    cout << thuong;
em chưa học đến cout chắc thầy ko cho dùng đâu, cơ mà để đó em tham khảo cũng hay
thuong=float(a)/b;
cách này cũng đc nhưng cũng phải khai float ở a bác ạ, nếu vậy thì như thím trên chỉ em thì ko cần folat chỗ a/b cũng ra kết quả
 
Foward này chưa đủ bác ơi. Bên dưới thấy ae khác comment đúng rồi đó
Thế phải làm gì nữa ạ? Em không lồng class vào được vì em cũng giải thích ở trên rồi. Hai class đó nằm ở hai files khác nhau.
 
Thế phải làm gì nữa ạ? Em không lồng class vào được vì em cũng giải thích ở trên rồi. Hai class đó nằm ở hai files khác nhau.
Bác không phải tách thành 2 file. Thực ra việc bác tách thành 2 file thì đến phase preprocessing nó cũng bị concatened lại thành 1 file thôi. Bác viết đủ declaration cho cả 2 class lên trên đi
 
Bác include của 2 file .h vào mỗi file cpp. Trong file IntArray thì forward declare IntArrayIterator, đã test và compile được rồi nhé.
Cảm ơn bác nhé. Thật ra cái class IntArrayIterator là nó thuộc về 1 file .h riêng, lẽ em phải #include vào nhưng để dễ đọc thì em bỏ cả vào 1 chỗ. Đó là yêu cầu của đầu bài ạ chứ nếu trộn chung vào thì nó lại không làm em đau đầu. Ngoài ra việc phải dùng reference cho iterator cũng là yêu cầu bắt buộc ạ. Còn vụ error handling thì em ghi nhận. Hiện tại em chưa làm gì vì đang tìm cách cho code nó chạy đã, error handling tính sau :D

Em có forward declaration ở trên cho compiler nó đọc rồi mà. Bác đọc trả lời của em ở trên để biết em buộc phải làm thế vì thực ra 2 classes này nằm ở 2 file khác nhau, lẽ ra em phải #include cái IntArrayIterator vào IntArray mới đúngác
 
Cảm ơn bác nhé. Thật ra cái class IntArrayIterator là nó thuộc về 1 file .h riêng, lẽ em phải #include vào nhưng để dễ đọc thì em bỏ cả vào 1 chỗ. Đó là yêu cầu của đầu bài ạ chứ nếu trộn chung vào thì nó lại không làm em đau đầu. Ngoài ra việc phải dùng reference cho iterator cũng là yêu cầu bắt buộc ạ. Còn vụ error handling thì em ghi nhận. Hiện tại em chưa làm gì vì đang tìm cách cho code nó chạy đã, error handling tính sau :D

Em có forward declaration ở trên cho compiler nó đọc rồi mà. Bác đọc trả lời của em ở trên để biết em buộc phải làm thế vì thực ra 2 classes này nằm ở 2 file khác nhau, lẽ ra em phải #include cái IntArrayIterator vào IntArray mới đúng.
Forward như vậy thì mới có tên class thôi, chưa có khai báo cái operator[] trong class IntArray thì làm sao compiler nó hiểu đc. Thử lại cái này xem:
C++:
#include <cstddef>
#include <iostream>

class IntArray;
class IntArrayIterator
{
private:
    const IntArray& fContainer;
    size_t fPosition;
public:
    IntArrayIterator(const IntArray& aContainer, size_t aStart = 0);
    const int operator*() const;
    IntArrayIterator& operator++(); // prefix
    bool operator==(const IntArrayIterator& aRHS) const;
    bool operator!=(const IntArrayIterator& aRHS) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

class IntArray
{
private:
    const int* fElements;
    size_t fNumberOfElements;
public:
    IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements);
    const int operator[](size_t aIndex) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

IntArrayIterator::IntArrayIterator(const IntArray& aContainer, size_t aStart): fContainer(aContainer), fPosition(aStart){}
const int IntArrayIterator::operator*() const
{
    return fContainer[fPosition];   
}
IntArrayIterator& IntArrayIterator::operator++()
{
    fPosition++;
    return *this;
}
bool IntArrayIterator::operator==(const IntArrayIterator& aRHS) const
{
    return fPosition == aRHS.fPosition;
}
bool IntArrayIterator::operator!=(const IntArrayIterator& aRHS) const
{
    return !(*this == aRHS);
}
IntArray::IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements) : fElements(aArrayOfIntegers), fNumberOfElements(aNumberOfElements){}
const int IntArray::operator[](size_t aIndex) const
{
    return fElements[aIndex];
}
IntArrayIterator IntArray::begin() const
{
    return IntArrayIterator(*this, 0);
}
IntArrayIterator IntArray::end() const
{
    return IntArrayIterator(*this, fNumberOfElements);
}
int main()
{
    int a[] = {5,10,15};
    IntArray iv(a, 3);
    for (const auto& it:iv)
    {
        std::cout << it << std::endl;
    }
    return 0;
}
 
class IntArrayIterator đâu có cần begin() end() làm gì đâu
xao ko xài thẳng luôn con chỏ, xài 1 cái ref với 1 cái index làm gì

IntArray.h
C++:
#ifndef INTARRAY_H
#define INTARRAY_H

// vì trong header của class IntArray có hàm trả về IntArrayIterator
// nên header file này cần biết thông tin đầy đủ của class IntArrayIterator,
// ko xài forward declaration được mà phải include
#include "IntArrayIterator.h"

class IntArray
{
private:
    const int* fElements;
    size_t fNumberOfElements;
public:
    IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements);
    const int operator[](size_t aIndex) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

#endif

IntArray.cpp
C++:
#include "IntArray.h"

IntArray::IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements)
: fElements(aArrayOfIntegers), fNumberOfElements(aNumberOfElements) {}

const int IntArray::operator[](size_t aIndex) const
{
    return fElements[aIndex];
}

IntArrayIterator IntArray::begin() const
{
    return IntArrayIterator(*this, 0);
}

IntArrayIterator IntArray::end() const
{
    return IntArrayIterator(*this, fNumberOfElements);
}

IntArrayIterator.h
C++:
#ifndef INTARRAYITERATOR_H
#define INTARRAYITERATOR_H

#include <cstddef> // cho size_t

// forward declaration để xài ref T& (hoặc con trỏ T*) tới class này.
// Nếu header này có xài thực thể của class (T) hoặc xài 1 hàm/biến
// T::member_function() hoặc T::member_variable thì ko xài forward
// declaration được mà phải include
// Vì header này chỉ xài ref tới IntArray nên ko cần include IntArray.h
// làm gì, tránh tạo include vòng
class IntArray;

class IntArrayIterator
{
private:
    const IntArray& fContainer;
    size_t fPosition;
public:
    IntArrayIterator(const IntArray& aContainer, size_t aStart = 0);
    int operator*() const; // trả về int được rồi const int làm gì
    IntArrayIterator& operator++(); // prefix
    bool operator==(const IntArrayIterator& aRHS) const;
    bool operator!=(const IntArrayIterator& aRHS) const;
};

#endif

IntArrayIterator.cpp
C++:
#include "IntArrayIterator.h"
// include IntArray.h trong file IntArrayIterator.cpp này
// vì file này cần biết hàm IntArray::operator[](size_t)
// include IntArray.h trong file .cpp này thì ko tạo include vòng.
#include "IntArray.h"

// include vòng xảy ra khi trong file IntArrayIterator.h có include IntArray.h,
// mà trong IntArray.h buộc phải include IntArrayIterator.h, thành ra 2 cái cần nhau
// tạo thành vòng include lẫn nhau, nên lệnh #include khi nó được preprocess nó copy
// nội dung 2 file này mãi ko thoát được dẫn tới lỗi.
// #include "IntArray.h" nó preprocess thành
//   <nội dung file IntArray.h>
// nội dung file này có include IntArrayInterator.h, vậy nó lại biến thành
//   <nội dung file IntArrayInterator.h>
//   <nội dung file IntArray.h>
// nhưng nội dung file IntArrayInterator.h lại có include IntArray.h, vậy nó lại biến thành
//   <nội dung file IntArray.h>
//   <nội dung file IntArrayInterator.h>
//   <nội dung file IntArray.h>
// v.v... lập vĩnh viễn. Xài forward declaration để break vòng lặp này

IntArrayIterator::IntArrayIterator(const IntArray& aContainer, size_t aStart)
: fContainer(aContainer), fPosition(aStart) {}

int IntArrayIterator::operator*() const
{
    return fContainer[fPosition];
}

IntArrayIterator& IntArrayIterator::operator++()
{
    fPosition++;
    return *this;
}

bool IntArrayIterator::operator==(const IntArrayIterator& aRHS) const
{
    return fPosition == aRHS.fPosition;
}

bool IntArrayIterator::operator!=(const IntArrayIterator& aRHS) const
{
    return !(*this == aRHS);
}

main.cpp
C++:
#include <iostream>

int main()
{
    int a[] = {5,10,15};
    IntArray iv(a, 3);
    for (auto it : iv) // mặc dù const auto& xài cũng được nhưng
                       // nên xài auto ở đây cho ít tốn chữ vì kiểu trả về của nó là int, copy lẹ.
                       // Hoặc ko biết nó trả về T hay T& thì xài hẳn auto&&
    {
        std::cout << it << std::endl;
    }
    return 0;
}
 
Last edited:
Forward như vậy thì mới có tên class thôi, chưa có khai báo cái operator[] trong class IntArray thì làm sao compiler nó hiểu đc. Thử lại cái này xem:
C++:
#include <cstddef>
#include <iostream>

class IntArray;
class IntArrayIterator
{
private:
    const IntArray& fContainer;
    size_t fPosition;
public:
    IntArrayIterator(const IntArray& aContainer, size_t aStart = 0);
    const int operator*() const;
    IntArrayIterator& operator++(); // prefix
    bool operator==(const IntArrayIterator& aRHS) const;
    bool operator!=(const IntArrayIterator& aRHS) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

class IntArray
{
private:
    const int* fElements;
    size_t fNumberOfElements;
public:
    IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements);
    const int operator[](size_t aIndex) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

IntArrayIterator::IntArrayIterator(const IntArray& aContainer, size_t aStart): fContainer(aContainer), fPosition(aStart){}
const int IntArrayIterator::operator*() const
{
    return fContainer[fPosition];  
}
IntArrayIterator& IntArrayIterator::operator++()
{
    fPosition++;
    return *this;
}
bool IntArrayIterator::operator==(const IntArrayIterator& aRHS) const
{
    return fPosition == aRHS.fPosition;
}
bool IntArrayIterator::operator!=(const IntArrayIterator& aRHS) const
{
    return !(*this == aRHS);
}
IntArray::IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements) : fElements(aArrayOfIntegers), fNumberOfElements(aNumberOfElements){}
const int IntArray::operator[](size_t aIndex) const
{
    return fElements[aIndex];
}
IntArrayIterator IntArray::begin() const
{
    return IntArrayIterator(*this, 0);
}
IntArrayIterator IntArray::end() const
{
    return IntArrayIterator(*this, fNumberOfElements);
}
int main()
{
    int a[] = {5,10,15};
    IntArray iv(a, 3);
    for (const auto& it:iv)
    {
        std::cout << it << std::endl;
    }
    return 0;
}

class IntArrayIterator đâu có cần begin() end() làm gì đâu
xao ko xài thẳng luôn con chỏ, xài 1 cái ref với 1 cái index làm gì

IntArray.h
C++:
#ifndef INTARRAY_H
#define INTARRAY_H

// vì trong header của class IntArray có hàm trả về IntArrayIterator
// nên header file này cần biết thông tin đầy đủ của class IntArrayIterator,
// ko xài forward declaration được mà phải include
#include "IntArrayIterator.h"

class IntArray
{
private:
    const int* fElements;
    size_t fNumberOfElements;
public:
    IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements);
    const int operator[](size_t aIndex) const;
    IntArrayIterator begin() const;
    IntArrayIterator end() const;
};

#endif

IntArray.cpp
C++:
#include "IntArray.h"

IntArray::IntArray(const int aArrayOfIntegers[], size_t aNumberOfElements)
: fElements(aArrayOfIntegers), fNumberOfElements(aNumberOfElements) {}

const int IntArray::operator[](size_t aIndex) const
{
    return fElements[aIndex];
}

IntArrayIterator IntArray::begin() const
{
    return IntArrayIterator(*this, 0);
}

IntArrayIterator IntArray::end() const
{
    return IntArrayIterator(*this, fNumberOfElements);
}

IntArrayIterator.h
C++:
#ifndef INTARRAYITERATOR_H
#define INTARRAYITERATOR_H

#include <cstddef> // cho size_t

// forward declaration để xài ref T& (hoặc con trỏ T*) tới class này.
// Nếu header này có xài thực thể của class (T) hoặc xài 1 hàm/biến
// T::member_function() hoặc T::member_variable thì ko xài forward
// declaration được mà phải include
// Vì header này chỉ xài ref tới IntArray nên ko cần include IntArray.h
// làm gì, tránh tạo include vòng
class IntArray;

class IntArrayIterator
{
private:
    const IntArray& fContainer;
    size_t fPosition;
public:
    IntArrayIterator(const IntArray& aContainer, size_t aStart = 0);
    int operator*() const; // trả về int được rồi const int làm gì
    IntArrayIterator& operator++(); // prefix
    bool operator==(const IntArrayIterator& aRHS) const;
    bool operator!=(const IntArrayIterator& aRHS) const;
};

#endif

IntArrayIterator.cpp
C++:
#include "IntArrayIterator.h"
// include IntArray.h trong file IntArrayIterator.cpp này
// vì file này cần biết hàm IntArray::operator[](size_t)
// include IntArray.h trong file .cpp này thì ko tạo include vòng.
#include "IntArray.h"

// include vòng xảy ra khi trong file IntArrayIterator.h có include IntArray.h,
// mà trong IntArray.h buộc phải include IntArrayIterator.h, thành ra 2 cái cần nhau
// tạo thành vòng include lẫn nhau, nên lệnh #include khi nó được preprocess nó copy
// nội dung 2 file này mãi ko thoát được dẫn tới lỗi.
// #include "IntArray.h" nó preprocess thành
//   <nội dung file IntArray.h>
// nội dung file này có include IntArrayInterator.h, vậy nó lại biến thành
//   <nội dung file IntArrayInterator.h>
//   <nội dung file IntArray.h>
// nhưng nội dung file IntArrayInterator.h lại có include IntArray.h, vậy nó lại biến thành
//   <nội dung file IntArray.h>
//   <nội dung file IntArrayInterator.h>
//   <nội dung file IntArray.h>
// v.v... lập vĩnh viễn. Xài forward declaration để break vòng lặp này

IntArrayIterator::IntArrayIterator(const IntArray& aContainer, size_t aStart)
: fContainer(aContainer), fPosition(aStart) {}

int IntArrayIterator::operator*() const
{
    return fContainer[fPosition];
}

IntArrayIterator& IntArrayIterator::operator++()
{
    fPosition++;
    return *this;
}

bool IntArrayIterator::operator==(const IntArrayIterator& aRHS) const
{
    return fPosition == aRHS.fPosition;
}

bool IntArrayIterator::operator!=(const IntArrayIterator& aRHS) const
{
    return !(*this == aRHS);
}

main.cpp
C++:
#include <iostream>

int main()
{
    int a[] = {5,10,15};
    IntArray iv(a, 3);
    for (auto it : iv) // mặc dù const auto& xài cũng được nhưng
                       // nên xài auto ở đây cho ít tốn chữ vì kiểu trả về của nó là int, copy lẹ.
                       // Hoặc ko biết nó trả về T hay T& thì xài hẳn auto&&
    {
        std::cout << it << std::endl;
    }
    return 0;
}
Cảm ơn hai sếp ạ :D
 
Back
Top